用过indy通讯的朋友请帮忙了:Idtcpclient连接到IdTcpserver之后,拔掉网线,服务器如何检测到(200分)

  • 主题发起人 主题发起人 sxzcm
  • 开始时间 开始时间
S

sxzcm

Unregistered / Unconfirmed
GUEST, unregistred user!
我试过thread.connection.CheckForGracefulDisconnect和CheckForDisconnect,竟然都认为该客户连接正常。
不采用客户端定时报告信息的方式,还有别的检测手段吗?
 
看来问题还是比较棘手的,还是大家用indy少
 
1层物理层都断,3层不会马上知道,idTcpserver会在30-90秒后有断开提示。建议采用定时报告的方式。
 
我都等了好长时间(3分钟有了)也没有收到disconnect事件。有人提出利用获取客户端IP的方法,但是connect.socket.binging.peerip是否一连接就固定了,也不能用来判断。就是找到了,ping回去成功也不见得说明客户连接还存在,因为有的客户端是固定IP,临时断开1分钟,再连接上了ip也不变
 
可以考虑用TCP自己的保活定时器,他的作用是每隔一段时间检查一下连接是否正常,如果不正常则报告给应用层。
用下面的方法试试,理论上应该是对的,偶没有实际测试:

uses WinSock;

在TCPServer的OnConnection事件里加上如下的片段:
procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
type
TCP_KeepAlive = record
OnOff: Cardinal;
KeepAliveTime: Cardinal;
KeepAliveInterval: Cardinal
end;
var
Val: TCP_KeepAlive;
Arg: Integer;
begin
Val.OnOff:=1;
Val.KeepAliveTime:=xxx;
Val.KeepAliveInterval:=xxx;
Arg:=Integer(@Val);
ioctlsocket(AThread.Connection.Socket.Binding.Handle,
$80000000 or $18000000 or 4, Arg);
end;

TCP_KeepAlive里的参数的意义是显而易见的,就不多说了。
然后连接将自动按指定间隔测试是否正常,作为应用程序可以在TCPServer的OnException里守着就行了。
 
心里没底,怕WinSock 1不支持,你最好还是用类似下面的片段吧。
uses WinSock2;

procedure TForm1.IdTCPServer1Connect(AThread: TIdPeerThread);
type
TCP_KeepAlive = record
OnOff: Cardinal;
KeepAliveTime: Cardinal;
KeepAliveInterval: Cardinal
end;
var
Val: TCP_KeepAlive;
Ret: DWord;
begin
Val.OnOff:=1;
Val.KeepAliveTime:=xxx;
Val.KeepAliveInterval:=xxx;
WSAIoctl(AThread.Connection.Socket.Binding.Handle, IOC_IN or IOC_VENDOR or 4,
@Val, SizeOf(Val), nil, 0, @Ret, nil, nil)
end;
 
谢谢,我试试
 
第一种方法(winsock)不行,我再试试后一种
 
第二种好像也不行,不知道是否和indy配合不好还是这些函数需要初始化
 
sorry,我错了,刚才测试第二种方法没有给参数赋值,现在赋值正确了,6000=6秒,拔掉网线6秒立即报告断开。成了了。祝贺大家,LeeChange劳苦功高,领得160分,element也说得有理,分40分。圆满完成
 
多人接受答案了。
 
后退
顶部