【问题标题】:How to find out if a socket is closed如何判断套接字是否关闭
【发布时间】:2012-10-07 03:47:23
【问题描述】:

我有一个简单的客户端服务器程序,但主要问题是一旦客户端和服务器之间建立连接,如果客户端关闭程序,服务器会重复执行最后一条消息,有时会产生巨大的问题.所以我想要的是,如果我可以调用任何函数来获取 SOCKET 结构的状态,那么如果客户端关闭程序,服务器就会知道停止。我只需要从函数中查找坏套接字的函数。顺便说一句,我正在用 Win32 c 编写这个程序。我试过 if(mySocket==SOCKET_ERROR) 似乎没有用......除非我用错了。我刚刚开始建立网络。

if(!sockServer.RecvData( recMessage, STRLEN )){return 0;}
// where
bool Socket::RecvData( char *buffer, int size )
{
    int i = recv( mySocket, buffer, size, 0 );
    if(!i){return false;}
    buffer[i] = '\0';
    return true;
}  //this isn't working

【问题讨论】:

    标签: c winapi sockets


    【解决方案1】:

    如果对等方关闭套接字,read()recv() 将返回零。您必须忽略如果“服务器重复执行最后一条消息”,这当然会“造成巨大的问题”,不仅仅是“有时”而是总是

    编辑 1: 您还犯了另一个基本的 TCP 编程错误:您假设您在一次读取中收到了完整的消息。 TCP 中没有消息,它只是一个字节流,写入和读取之间没有 1::1 的对应关系(send()recv())。 recv() 可以返回零或少至 1 个字节。您必须组织自己的消息边界,并且必须循环直到收到可以处理的完整消息。

    编辑 2: 您还忽略了接收方法中的所有错误。您必须寻找返回 -1 的 recv(),而不是继续处理您尝试读取的数据的逻辑。至少您应该调用 perror() 或检查 errno 或 Winsock 等效项。

    当您收到错误或 EOS 时,您必须停止循环,关闭套接字,忘记连接,忘记这个客户端。

    【讨论】:

    • 嗯,这似乎不起作用。我已经实现了我认为您在我的编辑中告诉我的上述操作
    • @Iowa15 你必须做的不止这些。您必须观察您的方法分别返回了falsezero;退出驱动这个逻辑的任何循环;关闭插座;并做任何其他需要做的事情来忘记这个套接字、这个客户端、这个连接。
    【解决方案2】:

    在主消息进程中监听 FD_CLOSE 怎么样?您正在使用带有 FD_CLOSE 的 WSAAsyncSelect 对吗?

    【讨论】:

    • 他想检测客户端是否结束了连接。服务器端套接字可能仍然有效。没有FD_CLOSE 不会有问题,因为当客户端结束时,服务器端套接字不会自动成为close()d。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-12-31
    • 1970-01-01
    • 2012-05-22
    • 2010-12-20
    • 2012-05-01
    • 1970-01-01
    相关资源
    最近更新 更多