6

我在 winsock 的 recv() 循环中遇到问题。我试图在 iResult==0 时终止循环,但是,循环仅在套接字关闭时结束。它似乎挂在 iResult 等于 0 的最后一个 recv() 处。那么关于如何有效终止循环的任何想法?我的最终目标(无论 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

谢谢

4

2 回答 2

4

默认情况下,recv 如果没有要接收的数据,则阻塞而不是返回 0 :

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

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

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

编辑:这是我在早期版本中提出的 setsockopt 建议,然后被删除(见评论):

如果没有可用数据,您可以使用setsockopt 函数和SO_RCVTIMEO选项将套接字设置为超时。recv

于 2010-07-27T02:37:55.350 回答
1

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

于 2010-07-27T03:35:42.887 回答