2016-11-13 13 views
0

У меня есть сервер-клиентское приложение, над которым я работаю, что в основном имитирует комнату чата. Это задание для школы, а спецификации протокола несколько строгие.Как превратить массив символов в uint8_t

У меня есть массив символов, который будет хранить все сообщения от клиента.

Клиент должен сначала отправить длину сообщения как uint8_t, а затем само сообщение как массив символов.

Моя проблема заключается в том, что мне нужно сохранить значение uint8_t, которое отправляется до отправки фактического сообщения, но я могу использовать только массив сообщений для хранения любой информации, поступающей от клиента.

Если я не ошибаюсь, массив символов не будет хранить uint8_t, который будет отправлен, если я не сделаю его каким-либо образом.

Как преобразовать uint8_t в символы и обратно в uint8_t?

Я пробовал искать аналогичную проблему здесь, но не смог найти пример.

server.c

char msg[100]; 
recv(clients_sd, msg, sizeof(msg), 0); 
uint8_t len; /* store the length of the message here */ 
char message_received[len]; 
recv(clients_sd, message_received, sizeof(message_received), 0); /* get and store the message here */ 

client.c

uint8_t length = 21; 
char clients_message[] = "Hi how are you today?"; 
send(servers_sd, &length, sizeof(length), 0); 
send(serers_sd, &clients_message, sizeof(clients_message), 0); 

ответ

3

Если вы на архитектуре, где uint8_t является typedef к unsigned char (вы, скорее всего, есть), то просто взять первый char и отличить его от uint8_t:

length = (uint8_t)(message_received[0]); 

Он должен работать.

+0

Я сделаю это. Благодаря! – fatalError

0

char может быть легко преобразован в uint8_t, но я не понимаю, почему вам нужно сохранить длину в массиве сообщений. Почему вы не можете хранить только переменную?

вот ваши примеры клиента и сервера с небольшими изменениями, которые я думаю, может быть полезным:

server.c

uint8_t len; /* store the length of the message here */ 
recv(clients_sd, &len, sizeof(len), 0);  
char message_received[len]; 
recv(clients_sd, message_received, len, 0); /* get and store the message here */ 

client.c

uint8_t length = 21; 
char clients_message[] = "Hi how are you today?"; 
send(servers_sd, &length, sizeof(length), 0); 
send(serers_sd, clients_message, lentgth, 0); 
1

char точно один байт (на определение стандарта C). Если байты не являются точно 8 битами в вашей системе (такие системы существуют, но я уверен, вы никогда не использовали или даже не видели один), uint8_t и char - это точно такой же тип данных.

char c = 5; 
uint8_t u = c; 

И если вы можете сделать что-то подобное с типом данных, то вы можете просто бросить указатели, как вы хотите между этими типами два данных:

char c[] = { 'H', 'e', 'l', 'l', 'o' }; 
uint8_t * u = (uint8_t *)c; 
uint8_t x = u[1]; 
// x is 101, which is the ASCII char code of 'e' 

На самом деле вы даже можете сделать это со строками , поскольку строка также представляет собой массив символов, только один, который заканчивается NUL.

char * c = "Hello"; 
// "Hello" is in fact just { 'H', 'e', 'l', 'l', 'o', '\0' } 
uint8_t * u = (uint8_t *)c; 
uint8_t x = u[1]; 
// x is 101, which is the ASCII char code of 'e' 

Единственное, что вам нужно быть осторожным в том, что стандарт C не определяет, если char подписано или без знака. В отличие от целочисленных типов, которые по умолчанию подписаны и только без знака, если вы запрашиваете это (long, например, unsigned long), по умолчанию могут быть подписаны или без знака char. Поэтому, если вам нужен один, вы должны использовать signed char или unsigned char в качестве типа данных. На практике это не играет никакой роли, если вы не выполняете определенные математические или логические операции по значениям char (чего вы, вероятно, не должны делать в современном C-коде для начала).

И поскольку нет никакого способа, что ваше сообщение может быть больше, чем 256 символов (как в противном случае длина не будет вписываться в uint8_t), а длина всегда ровно один байт, я бы написать код следующим образом:

uint8_t messageLength = 0; 
ssize_t bytesRead = recv(clients_sd, &messageLength, 1, 0); 
if (bytesRead == -1) { 
    // Handle read error 
} 
if (bytesRead == 0) { 
    // Handle end of stream 
} 

char message[256]; 
bytesRead = recv(clients_sd, message, messageLength, 0); 
if (bytesRead == -1) { 
    // Handle read error 
} 
if (bytesRead == 0) { 
    // Handle end of stream 
} 
if (bytesRead < messageLength) { 
    // Handle truncated message (message too small) 
} 

И еще раз, поскольку, по-видимому, некоторые люди уже не понимают мое второе предложение: все, что я написал выше, в предположении, что байты в вашей системе имеют длину 8 бит. Этот код не переносится на платформы, где байты имеют более или менее 8 бит, это уже то, что ясно указывает мое второе предложение, но это не делает мой ответ неправильным. Если бы не было разрешено писать C-код, который не переносится на все существующие платформы на земле, 90% всего существующего кода C было бы запрещено. Вы знаете платформу, с которой работаете, и вы знаете, на каких платформах вы ориентируетесь с вашим приложением, поэтому ваша ответственность - убедиться, что код верен для всех этих платформ.

+0

uint8_t не гарантирует синонимы типа символа. Таким образом, использование - это псевдоним всех типов, поскольку типы символов могут быть, не переносимы. – 2501

+0

@ 2501 Пожалуйста, объясните, какая часть «* Если в вашей системе нет байтов не 8 бит (такие системы существуют, но я уверен, вы никогда не использовали или даже не видели), uint8_t и char - это точно такой же тип данных. * «Ты точно не понимал? Вы знаете смысл слова, если только? Пожалуйста, прекратите вкладывать слова во рту, о которых я никогда не говорил. И, пожалуйста, воздержитесь от комментариев, которые вы явно не читали. – Mecki

+0

@ 2501 «char» всегда точно байт, стандарт C требует этого! И если у байта 8 бит в вашей системе (** и я явно предупреждал, что это не обязательно так !!! **), то 'uint8_t' также является байтом. Пожалуйста, объясните миру, как байт не может быть байтом, поскольку стандарт C также требует, чтобы, если существует собственный 8-битный тип, 'uint8_t' должен быть этим типом, а если' char' - 8 бит, то такой родной тип должен существовать. Поэтому ваш комментарий даже не имеет смысла. – Mecki