терминатор разговора сокета - PullRequest
0 голосов
/ 15 апреля 2011

При чтении данных в сокете важно либо сохранить message terminator symbo l, либо добавить Packet size information в начале сообщения.

Если используется символ-терминатор и отправлено двоичное сообщение, то оно есть.нет никакой гарантии, что символ-терминатор не появится в середине сообщения (если не используется специальная кодировка).

С другой стороны, если информация о размере прилагается.информация о размере не подписана, и если для нее используется один байт, ее нельзя использовать для передачи сообщений длиннее 256 байт.если используется 4-байтовое целое числодаже не гарантируется, что 4 байта будут целиком.может поступить только 2 байта информации о размере, если предположить, что информация о размере поступила, может использоваться 2 байта, а остальные целочисленные данные будут отброшены.ожидание 4 байтов, доступных в буфере чтения, может привести к бесконечному ожиданию, если в буфере доступно только 3 байта (например, если общий буфер имеет длину 7 байтов или 4077 байтов).

здесь возможны два варианта

  1. блок-разделитель sizeInfo

    считывание до тех пор, пока не будет найден разделитель, считывание до тех пор, пока sizeInfo байт не пройдено

  2. сохранить инициализацию unreadyBytes на 4 при полученииsizeInfo изменить его соответственно

, какой из этих двух безопаснее использовать?Пожалуйста, критикуйте

Редактировать

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

1 Ответ

1 голос
/ 15 апреля 2011

даже не гарантируется, что 4 байта будут целиком.может поступить только 2 байта информации о размере, если предположить, что информация о размере поступила, может использоваться 2 байта, а остальные целочисленные данные будут отброшены.ожидание 4 байтов для буфера чтения может привести к бесконечному ожиданию, если в буфере доступно только 3 байта (например, если общий буфер имеет длину 7 байтов или 4077 байтов).

Если у вас естьДескриптор длиной 4 байта, вы всегда должны читать как минимум 4 байта, потому что отправитель должен был записывать эти байты в каждом сообщении, которое получает ваш сервер.Если вы не можете их получить, возможно, возникла проблема при передаче.Я действительно не могу понять вашу проблему.

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

Вы должны по крайней мере прочитать заголовок пакета, чтобы определить его длину.

Вы можете определитьБазовая структура пакета:

struct packet{
     uint32 id;
     char payload[MAX_PAYLOAD_SIZE];
};

Данные, которые вы читаете из сокета и сохраняете их в буфере:

struct packet buffer;

Затем вы можете прочитать данные из сокета: int n;n = read (newsocket, & buffer, sizeof (uint32) + MAX_PAYLOAD_SIZE);

read возвращает количество прочитанных байтов.Если вы точно прочитали пакет от отправителя, то n = id.В противном случае, возможно, вы прочитаете больше данных (например, отправитель отправил вам больше пакетов).Если вы получаете поток данных, разделенных на блоки (представленные структурами пакетов), вы можете использовать массив пакетов для хранения всего полученного пакета и временный буфер для управления входящими фрагментами.Что-то вроде:

буфер структурных пакетов [MAX_PACKET_STORED];char temp_buffer [MAX_PAYLOAD_SIZE + 4];

int n;n = read (newsocket, & buffer, sizeof (uint32) + MAX_PAYLOAD_SIZE);

// здесь предположим, что получили пакет с полезной нагрузкой 100 байт + длина 32 бита + 100 байт // фрагменты следующего пакета.// затем:

int first_pack_len, second_pack_len;

first_pack_len = *((uint32 *)&temp_buffer[0]); //retrieve packet length

memcpy(&packet_buffer[0], temp_buffer, first_pack_len + sizeof(uint32)) //store the first packet into the array

second_pack_data_available_in_buffer = n - (first_pack_len + sizeof(uint32)); //total bytes read minus length of the first packet read
second_pack_len = *((int *)&temp_buffer[first_pack_len + sizeof(uint32)]);

Я надеюсь, что все было достаточно ясно.Но, возможно, я неправильно понимаю ваш вопрос.Обратите также внимание на то, что если у двух конечных систем, имеющих связь, могут быть разные порядковые номера, то лучше использовать функцию длины htonl / ntohl при отправке / получении значения длины.Но это другой вопрос)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...