首页 文章

为什么在连接关闭时recv有时不会返回?

提问于
浏览
0

我有一个简单的winsock客户端/服务器应用程序 . 大多数情况下一切正常,但有时即使客户端应用程序终止,recv也不会返回值 .

从MSDN引用:

如果没有错误发生,recv返回接收的字节数,buf参数指向的缓冲区将包含接收到的数据 . 如果已正常关闭连接,则返回值为零 . 否则,返回值SOCKET_ERROR,并且可以通过调用WSAGetLastError来检索特定的错误代码 .

如果没有与客户端的连接,那么recv永远不会返回并永远挂起的原因是什么?

相关的服务器代码:

const
  BUFSIZE = 512;
var
  Sock: TSocket;
  I   : Integer;
  Buf : AnsiString;
begin
  repeat
    SetLength(Buf, BUFSIZE);
    //blocking call
    I := recv(Sock, Pointer(Buf)^, BUFSIZE, 0);
    if I > 0 then
    begin
      SetLength(Buf, I);
      //do s.th. with Buf
    end;
  until I <= 0; //Connection closed or error

  //Sometimes never here

  Synchronize(procedure
  begin
    FOnConnectionClosed(Self, Sock, WSAGetLastError);
  end);
end.

2 回答

  • 0

    '如果连接已正常关闭' - 如果它没有正常关闭,(有人在客户端拔出网线),服务器recv()调用将继续等待,很可能永远等待 . 您可以设置KEEPALIVE套接字选项,但默认情况下这将花费很长时间来检测半开套接字,此外,KEEPALIVE超时值是全局注册表值:(

    您可以使用SO_RCVTIMEO setsockopt()选项在recv()上设置较小的每插槽超时 . 您可以使用此超时来立即关闭套接字,或者,如果您的协议允许,则向对等方发出某种轮询/回应请求以确保它仍然存在,如果发生另一个超时,则关闭套接字 .

  • 0

    recv() 永远不会阻止正常断开连接(发送 FIN 数据包) . 因此,它实际上并不是一个优雅的断开连接,或者您的读取代码与您的套接字不同步,并且您实际上并没有从您认为正在读取的套接字中读取 .

相关问题