recv читает неполный пакет

У меня есть простая функция, отвечающая за получение пакетов через сокет.

if((recv_size = recv(sock , rx , 50000 ,0)) == SOCKET_ERROR)
  {
    ...                         
  } else
  {
    ...
  }

Я обнаружил, что иногда получаю неполный пакет. Почему? Может быть, мне следует использовать recv несколько раз? Длина пакета никогда не превышает 50000 байт.

Я использую сокет TCP.


person vico    schedule 21.05.2015    source источник
comment
Какую розетку вы используете? UDP или TCP? В TCP может потребоваться использовать несколько раз recv.   -  person AdamF    schedule 21.05.2015


Ответы (1)


Если вы используете TCP, это ожидаемо. TCP – это протокол потоковой, в нем нет "пакетов" или границ сообщений, и вы можете получить все "сообщение" или его часть, или даже несколько сообщений. Поэтому вам, возможно, придется вызвать recv несколько раз, чтобы получить полное сообщение.

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

person Some programmer dude    schedule 21.05.2015
comment
Но что, если данных больше не будет, и я снова вызову recv. В этом случае я буду вечно ждать возврата этой функции. - person vico; 21.05.2015
comment
@vico Вы должны указать recv читать только до тех пор, пока вы не используете все ожидаемые данные, которые вы бы определили, прочитав заголовок фиксированной длины или какой-либо маркер конца сообщения. Если вам интересно, как справиться с ожиданием новых сообщений после того, как вы закончите получать предыдущее, вам нужно добавить потоки на свой сервер, чтобы вы не блокировались, ожидая, пока recv что-то вернет. - person chemdt; 21.05.2015
comment
@vico Если в вашем протоколе есть границы или длина сообщений, вы можете прочитать точное необходимое количество (возможно, с несколькими вызовами) или вы можете использовать, например. seelct или poll, чтобы увидеть, когда есть данные для чтения без блокировки принимающей функции, или вы можете использовать неблокирующие сокеты. - person Some programmer dude; 21.05.2015