Завершение цикла " recv ()", когда вся информация считывается с помощью Winsock


У меня возникла проблема в цикле recv() для winsock. Я пытаюсь завершить цикл, когда iResult= = 0, однако цикл заканчивается только тогда, когда сокет закрывается. Похоже, что он висит на самом последнем recv (), где iResult будет равен 0. Итак, есть идеи о том, как эффективно завершить цикл? Моя конечная цель (независимо от того, является ли iResult = = 0 или нет; возможно, я иду по этому неверному пути) - остановить цикл, когда вся отправленная информация была прочитана. Вот такая петля.

    do
    {
        iResult = recv(socket, recvbuf, BUFLEN-1, 0);
        if(iResult > 0){
            // Null byte :)
            // Remove that garbage >:(
            recvbuf[iResult] = '';
            printf("Recvbuf: %snnniResult: %dn",recvbuf,iResult);
            continue; // working properly
        }
        else if(iResult == 0)
            // Connection closed properly
            break;
        else
        {
            printf("ERROR! %ld",WSAGetLastError());
            break;
        }
    } while(iResult > 0);

Как Я сказал, что я получаю все данные, я просто не могу выйти из цикла. Следующим шагом будет запись данных обратно на сервер,но он зависает здесь до времени ожидания ping. Сокет sock_stream и BUFLEN определяется как 0x200

Спасибо

2 6

2 ответа:

По умолчанию вместо возврата 0, recv блоки, если нет данных для получения :

Если никакие входящие данные не доступны на сокет, блоки вызова recv и ожидает поступления данных в соответствии с правила блокировки, определенные для WSARecv с флагом MSG_PARTIAL не установлен если только сокет не блокируется. В в этом случае значение SOCKET_ERROR равно возвращается с кодом ошибки, установленным в WSAEWOULDBLOCK. Отбор, WSAAsyncSelect, или WSAEventSelect функции можно использовать для определения при поступлении дополнительных данных.

Вы можете использовать ioctlsocket для перевода сокета в неблокирующий режим:

u_long iMode = 1;
ioctlsocket(socket, FIONBIO, &iMode);

EDIT : Вот предложение setsockopt, которое я сделал в предыдущем rev, а затем удалил (см. комментарии):

Вы можете использовать setsockopt функция с параметром SO_RCVTIMEO чтобы установить сокет в таймаут на recv если данные отсутствуют.

При разработке механизма связи TCP необходимо определить границы сообщений. (часто \r\n). Сам по себе tcp не знает границ; вы должны сделать это сами. Вызов recv () может не всегда возвращаться на границу сообщения. Один send () может быть разделен на несколько recv ()-s на другом конце.