recv() возвращает 0
У меня очень раздражающая проблема, которую я обнаружил несколько раз на других форумах, но не могу найти правильного решения. Проблема в том, что recv () возвращает 0 в последние несколько байтов соединения. Вот некоторая справочная информация.
- Оба (клиент / сервер) приложения работают на одном компьютере.
- Оба (клиент / сервер) сокета не блокируют
- Размер передаваемых данных составляет 53 байта.
- Оба (клиент / сервер) вызывают завершение работы и closesocket, когда выполнялась последняя функция send()/recv().
- Я также пытался с SO_LINGER и 10 секунд, но безуспешно
Я вызываю send () несколько раз (небольшими порциями) и со стороны клиента передается 53 байта. Сервер вызывает recv () несколько раз (запросы 4 байта) и читает 49 байтов, а затем возвращает 0 (54 байта - 49 байтов, поэтому 4 байта отсутствуют).
MSDN и некоторые форумы пишут для неблокирующих сокетов:
- recv () определенно возвращает < 0 в случае ошибки и устанавливается errno / WSAGetLastError
- recv () определенно возвращает = 0, когда другая сторона закрыла соединение
- recv () определенно возвращает> 0, когда данные были прочитаны
MSDN также говорит:
Использование функций closesocket или shutdown с SD_SEND или SD_BOTH приводит к отправке сигнала RELEASE по каналу управления. Из-за использования банкоматом отдельных каналов сигналов и данных, возможно, что сигнал RELEASE может достичь удаленного конца до того, как последние данные достигнут пункта назначения, что приведет к потере этих данных. Одним из возможных решений является программирование достаточной задержки между последними отправленными данными и вызовами функции closesocket или shutdown для сокета ATM.
Это рассматривается в примере с recv () и send (): http://msdn.microsoft.com/en-us/library/windows/desktop/ms740121(v=vs.85).aspx
Но все равно безуспешно, я все еще получаю некоторые прерывания в 10% всех соединений после получения 49 байтов, 90% соединений успешны. Есть идеи? Спасибо.
2 ответа
recv()
возвращает 0 только тогда, когда вы запрашиваете 0-байтовый буфер или другой узел изящно отключился. Если вы не получаете все ожидаемые данные, то вы не правильно читаете данные для начала. Пожалуйста, обновите ваш вопрос с вашим реальным кодом.
- recv() определенно возвращает = 0, когда другая сторона закрыла соединение
Это не совсем так, в следующем коде, использующем неблокирующий winsock2 tcp, когда данные недоступны, select возвращает 1, а recv возвращает 0, как и WSAGetLastError().
fd_set test = {1, socket};
const timeval timeout = {0, 0};
if (!::select(0, &test, nullptr, nullptr, &timeout)) return 0;
int done = ::recv(socket, buffer, 1, 0);
Это продолжается даже после вызова с другого конца:
::shutdown(socket, SD_BOTH);
::closesocket(socket);
а потом закончилось. Связь работает как положено, просто::recv кажется "сломанным".
Я предполагаю, что вы на самом деле не отправляете все данные, которые, по вашему мнению, отправляете. Проверять, выписываться: