我最近在做一个cs结构的应用,客户端需要和服务器一直长期保持连接,且客户端无人值守,我令客户端每1分钟测试一下和服务器的连接(采用收发验证数据),当连接异常中断的时侯客户端重新发起连接。可是我发现有如下问题:
客户端每发起一次连接,服务器端都会产生一个相应的线程来相应,但是服务端以前响应该客户端的线程并没有结束(原来的线程会一直在ReadLn处等待),也就是说服务器端的线程数量会越来越多,这样肯定是不行的,因为我的客户端和服务器一直保持连接要6个月以上。我想问的是如何让服务器根据网络的异常情况释放掉对应线程,让服务器端对每一个客户端只有一个响应的线程,而不是有多个响应的线程。谢谢回答!
客户端每发起一次连接,服务器端都会产生一个相应的线程来相应,但是服务端以前响应该客户端的线程并没有结束(原来的线程会一直在ReadLn处等待),也就是说服务器端的线程数量会越来越多,这样肯定是不行的,因为我的客户端和服务器一直保持连接要6个月以上。我想问的是如何让服务器根据网络的异常情况释放掉对应线程,让服务器端对每一个客户端只有一个响应的线程,而不是有多个响应的线程。谢谢回答!
if AThread.Terminated or (not AThread.Connection.Connected) then exit;TIdTcpServer最多可以连接不到2K个客户端,写过测试程序。
unit utils_socketc;interface
uses IdStackConsts,IdStackWindows,IdWinSock2;const
IOC_IN =$80000000;
IOC_VENDOR =$18000000;
SIO_KEEPALIVE_VALS =IOC_IN or IOC_VENDOR or 4;
type tcp_keepalive=record
onoff:Longword;
keepalivetime:Longword;
keepaliveinterval:Longword;
end;
//设置KeepAlive用于检测线路是否中断function SetKeepALive(const SockHandle:integer):Boolean;
implementation
function SetKeepALive(const SockHandle:integer):Boolean;
var
KeepAliveIn : tcp_keepalive;
KeepAliveOut : tcp_keepalive;
Status : Integer;
BytesReturned : Cardinal;
Akeepalivetime,Akeepaliveinterval:integer;
begin
Result:=false;
//启用KeepALive
KeepAliveIn.onoff:=1;
//发送检测包间隔(2s)
KeepAliveIn.keepalivetime:=2000;
//回应超时(1s),默认情况下,如果出现超时,Windows将重新发送检测包,直到5次全部失败。
KeepAliveIn.keepaliveinterval:=1000;
Status:=WSAIoctl(SockHandle, SIO_KEEPALIVE_VALS,
@KeepAliveIn, SizeOf(KeepAliveIn),
@KeepAliveOut, SizeOf(KeepAliveOut),
@BytesReturned, nil, nil);
if Status <> 0 then
begin
showmsgc.showNormal_msg('SetKeepAlive error','');
exit;
end;
Result:=true;
end;
end.调用
SetKeepALive(self.IdTCPClient.Socket.Binding.Handle);另外一个简单方法是在idtcpserver的onconnect消息中,为每个连接设置读超时,ReadLn在达到读超时后,出现一个错误,用try except可以捕捉到,然后disconnect就可以了。
begin
c:=Form1.TCPClient.ReadFromStack(True,-2,True);
if c<1 then Continue;
try
Form1.TcpClient.ReadBuffer(F,SizeOf(F));
Form1.TcpClient.ReadBuffer(Verify,SizeOf(Verify));
....
except
Synchronize(DisplayError);//由于没有得到数据,每次都显示"线程执行错误!!!"
end;
end
...
procedure TReadThread.DisplayError;
begin
Form1.StatusBar.Panels.Items[2].Text:='线程执行错误!!!';
end;ReadFromStack 检测有没有数据到达,并返回字节数
但不知为何报read timeout?