Delphi + Synapse:如何检查是否仍然连接

7
我正在使用TTCPBlockSocket来开发TCP/IP应用程序。问题在于我无法确定连接何时丢失。

GetLastError返回0
Read返回0

即使应用程序已连接,我仍会遇到这些值,因此我该如何被通知TCP/IP连接何时丢失。

谢谢


我会说,你要找的是将0作为“Timeout”参数传递的CanRead函数调用。该函数内部调用InternalCanRead,该函数执行Winsock select函数。如果发生任何错误,则CanRead函数返回False。 - TLama
@TLama,你的回答让我找到了正确的方向,但是必须满足以下条件才能检查它是否已断开连接:如果TCPBlockSocket.CanRead(0)和TCPBlockSocket.WaitingData = 0,则disconnected := true。你可以将此作为答案发布,以便我接受。 - opc0de
@TLama 是突触专家! - PFeng
3个回答

1

我认为,您可以使用CanRead方法,并将0传递给其Timeout参数。该函数在套接字上内部执行select函数,并在发生错误时返回False。仅使用此方法应该足够了,因为如果您失去连接,则select函数返回SOCKET_ERROR,并导致CanRead方法返回False。因此,我认为通过这种方式检查套接字连接是否存活就足够了:

function IsSocketAlive(ASocket: TTCPBlockSocket): Boolean;
begin
  Result := ASocket.CanRead(0);
end;

不行,仅凭这个还不够,你需要自己测试。对此我给予加一的支持。 - opc0de
“WaitingData”方法(如您添加的)返回网络输入缓冲区中挂起数据的数量,如果该内部“ioctlsocket”函数调用未失败并返回在您连接丢失时待处理的数据量,则不符合您的需求。或者我错了吗?(不幸的是,我现在无法测试它) - TLama

1
正如opC0de所说,要检查客户端是否仍然连接,您需要同时检查TCPBlockSocket.CanRead(0)和TCPBlockSocket.WaitingData = 0。
function IsSocketAlive(ASocket: TTCPBlockSocket): Boolean;
begin
  Result := (ASocket.Socket = INVALID_SOCKET) or ((ASocket.WaitingData = 0) and ASocket.CanRead(0));
end;

我在我的项目中使用这种方法,所以我可以确认它是有效的。

0

我之前使用了kattunga的答案,但在进行压力测试时遇到了很多误报触发。我的假设是,在等待数据和可读条件之间,有时会出现数据包到达服务器的情况,导致服务器认为套接字已经死亡。 我改变了条件的顺序,问题就解决了。

function TTCPSynWorkThread.IsSocketDead(ASocket: TTCPBlockSocket): boolean;
begin 
  Result := (ASocket.Socket = INVALID_SOCKET) or (ASocket.CanRead(0) and (ASocket.WaitingData = 0));
end;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接