recv() с MSG_PEEK показывает полное сообщение, но возвращает нормально блокируемый
У меня есть неблокирующее гнездо winsock, которое recv
данные в цикле.
Я заметил, что при соединении, скажем, с putty и необработанным сокетом, отправка сообщений работает просто отлично. Однако при взаимодействии с этим конкретным клиентом пакеты, по-видимому, не вызывают успешное, неMSG_PEEK
позвонить recv
, Я помню, что несколько лет назад у меня была похожая проблема, и в итоге пришлось \r
или что-то от клиента, что в данном случае невозможно, так как я не могу изменить клиента.
Wireshark показывает пакеты, проходящие через очень хорошо; моя серверная программа, однако, работает не совсем правильно.
Как бы я это исправить?
РЕДАКТИРОВАТЬ: Уменьшение размера буфера, скажем, до 8 привело к нескольким успешным вызовам recv без MSG_PEEK.
Recv call:
iLen = recv(group->clpClients[cell]->_sock, // I normally call without MSG_PEEK
group->clpClients[cell]->_cBuff, CAPS_CLIENT_BUFFER_SIZE, MSG_PEEK);
if(iLen != SOCKET_ERROR)
{
...
Гнездо есть AF_INET
, SOCK_STREAM
а также IPPROTO_TCP
,
4 ответа
Документация Microsoft в нескольких местах гласит, что MSG_PEEK
следует избегать в целом, потому что это неэффективно и неточно. использование select()
, WSAAsyncSelect()
, или же WSASelectEvent()
вместо этого, чтобы определить, когда сокет имеет данные, доступные для чтения, затем вызвать recv()
в WSARecv()
на самом деле читать это.
Решение оказалось специфичным для реализации; Я знал, что длина всех пакетов, поступающих от клиента, делится на определенное количество байтов. Итак, я просто прочитал это количество байтов, пока буфер не был пуст.
Макс. количество байтов, которое вы можете получить за раз в этой ситуации, должно быть меньше максимальной длины самого длинного сообщения и должно быть GCF (величайшим общим фактором) этой длины.
Это далеко не постоянное решение, но пока работает.
Сокет TCP - это поток байтов, он не сохраняет границы сообщений вашего приложения. Как только ядро может вам что-то дать, оно возвращается из опроса. Вы должны собирать полученные байты, пока у вас не будет достаточно для декодирования того, что вам нужно для декодирования.