当使用Winsock读取所有信息时,结束“recv()”循环

时间:2010-07-27 02:16:25

标签: c++ windows winapi winsock recv

我在winsock的recv()循环中遇到了问题。我试图在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] = '\0';
            printf("Recvbuf: %s\n\n\niResult: %d\n",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 个答案:

答案 0 :(得分:4)

默认情况下,recv blocks if there's no data to receive

不是返回0
  

如果没有可用的传入数据   套接字,recv调用块和   根据数据等待数据到达   为WSARecv定义的阻止规则   未设置MSG_PARTIAL标志   除非套接字是非阻塞的。在   在这种情况下,SOCKET_ERROR的值是   返回错误代码设置为   WSAEWOULDBLOCK。选择,   WSAAsyncSelect或WSAEventSelect   函数可用于确定   当更多数据到达时。

您可以使用ioctlsocket将套接字置于非阻塞模式:

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

编辑:这是我在之前版本中制作的setsockopt建议,然后删除(请参阅评论):

  

您可以使用setsockopt   使用SO_RCVTIMEO选项运行   在recv上将套接字设置为超时   如果没有数据可用。

答案 1 :(得分:1)

设计TCP通信机制时,必须定义消息边界。 (经常\ r \ n)。就其本身而言,tcp不了解边界;你必须自己做。 recv()调用可能并不总是在消息边界上返回。一个send()可能会在另一端拆分为多个recv() - 。