如何在不关闭服务器套接字的情况下在C ++客户端的主循环中接收数据?

时间:2012-02-28 18:49:30

标签: c++ sockets

我正在阅读this winsock example

我试图概念化如何创建一个与C#.NET服务器具有持久TCP / IP连接的C ++客户端程序。

我看到的问题是,为了让C ++客户端离开接收循环,服务器必须关闭其与客户端的套接字连接。

在我的情况下,服务器将每隔几秒发送给客户端。我需要能够从服务器接收一个数据包并重新启动主程序循环,以便客户端可以执行其余的功能。

如果此接收代码位于C ++客户端的主循环中,则如果服务器永远不会关闭与客户端的连接,则客户端将永远不会停止接收:

// Receive until the peer closes the connection

do {

    iResult = recv(ConnectSocket, recvbuf, recvbuflen, 0);
    if ( iResult > 0 )
        printf("Bytes received: %d\n", iResult);
    else if ( iResult == 0 )
        printf("Connection closed\n");
    else
        printf("recv failed with error: %d\n", WSAGetLastError());

} while( iResult > 0 );

2 个答案:

答案 0 :(得分:2)

您选择使用的示例程序旨在发送单个请求并接收单个响应。它使用连接状态来指示请求的结束和响应的结束。

您可能希望使用其他示例程序。在谷歌上搜索“winsock聊天示例”。

另一方面,要按照你的要求修改这个程序,你可以用这个替换do-while循环:

// Assume that the OP's protocol sends 100-byte packets. 
// Each while iteration attempts to receive one such packet.
// The while exits when the other side closes its connection.
while(1) {
    // Receive 100-byte packet 
    int receivedBytes;
    for(receivedBytes = 0; receivedBytes < 100; ) {
        int iResult = recv(ConnectSocket,
                           recvbuf+receivedBytes,
                           recvbuflen-receivedBytes, 0);

        if ( iResult > 0 ) {
            receivedBytes += iResult;
            printf("Bytes received: %d\n", iResult);
        } else if ( iResult == 0 ) {
            printf("Connection closed\n");
            break;
        } else {
            printf("recv failed with error: %d\n", WSAGetLastError());
            break;
        }
    }
    if(receivedBytes == 100) {
        // ... process packet here
    } else {
        break;
    }
}

答案 1 :(得分:1)

这里的问题是你无法知道recv()将在什么时候返回。有五种解决方法:

  1. 使套接字无阻塞。 (不推荐)
  2. 暂停使用select()
  3. 使用异步套接字。这可能是最快的方式,但更复杂。
  4. 使用线程。
  5. BSD kqueue