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

Delphi 为什么连接关闭时recv有时不返回?,delphi,return,winsock,recv,Delphi,Return,Winsock,Recv,我有一个简单的winsock客户机/服务器应用程序。大多数情况下,一切正常,但有时recv即使在客户端应用程序终止时也不会返回值 引用MSDN: 如果未发生错误,recv将返回接收的字节数和 buf参数指向的缓冲区将包含此数据 收到。如果连接已正常关闭,则返回 值为零。否则,将返回SOCKET_ERROR的值,并且 可以通过调用WSAGetLastError检索特定的错误代码 没有与客户端的连接,recv永远不会返回并挂起的原因可能是什么 相关服务器代码: const BUFSIZE = 5

我有一个简单的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.
const
BUFSIZE=512;
变量
短袜:短袜;
I:整数;
Buf:AnsiString;
开始
重复
设置长度(Buf,BUFSIZE);
//阻塞呼叫
I:=recv(Sock,指针(Buf)^,BUFSIZE,0);
如果I>0,那么
开始
设定长度(Buf,I);
//做s.th。带Buf
结束;

直到I“如果连接已正常关闭”-如果连接未正常关闭,(有人在客户端拔出网络电缆),server recv()调用将继续等待,很可能永远不会停止。您可以设置KEEPALIVE套接字选项,但默认情况下,检测半开套接字需要很长时间,而且KEEPALIVE超时值是一个全局注册表值:(


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

recv()
不会在正常断开连接时阻塞(发送
FIN
数据包的断开连接)。因此,这可能不是一个正常的断开连接,或者您的读取代码与套接字不同步,并且您实际上不是从您认为读取的套接字进行读取。

谢谢您的回答,但有时在客户端应用程序正常关闭时(未拔出网线)也会发生这种情况。这是怎么回事?KEEPALIVE可以在每个连接的基础上设置,它不是全局的。您也可以使用
select()
而不是
SO\u RCVTIMEO
来检测数据何时可用,或者是否发生了正常断开连接,然后再使用
recv()
读取数据。