服务端的心跳处理(idtcpserver) //定义心跳常量 Const IOC_IN = $80000000; IOC_VENDOR = $18000000; IOC_out = $40000000; SIO_KEEPALIVE_VALS = IOC_IN or IOC_VENDOR or 4; DATA_BUFSIZE = 8192; //定义 KeepAlive 数据结构 Type TTCP_KEEPALIVE = packed record onoff: integer; keepalivetime: integer; keepaliveinterval: integer; end; 在idtcpserver的OnConnect事件里面加入以下代码: var opt:Integer; klive, outKlive: TTCP_KEEPALIVE; begin opt := 1; if setsockopt(AThread.Connection.Socket.Binding.Handle,SOL_SOCKET, SO_KEEPALIVE, @opt, SizeOf(opt)) <> 0 then begin Showmessage('setsockopt KeepAlive Error!'); end; klive.onoff := 1; klive.keepalivetime := 3000; klive.keepaliveinterval := 1; if WSAIoctl(AThread.Connection.Socket.Binding.Handle, SIO_KEEPALIVE_VALS, @klive, SizeOf(TTCP_KEEPALIVE), @outKlive, SizeOf(TTCP_KEEPALIVE), @opt,0,nil) = SOCKET_ERROR then begin Showmessage('WSAIoctl KeepAlive Error!'); end end 在idtcpserver的OnException事件里面就能捕获到这个异常,并进行异常处理了 procedure Tfrmmain.IdTCPServer1Exception(AThread: TIdPeerThread; AException: Exception); begin suiMemo1.Lines.Add('客户端'+inttostr(athread.handle)+'异常断开'); if AThread.Connection.Connected then AThread.Connection.Disconnect; end; 客户端的心跳处理(idtcpclient) procedure Tfrmmain.IdTCPClient1Connected(Sender: TObject); var opt:Integer; klive, outKlive: TTCP_KEEPALIVE; begin opt := 1; if setsockopt(IdTCPClient1.Socket.Binding.Handle,SOL_SOCKET, SO_KEEPALIVE, @opt, SizeOf(opt)) <> 0 then begin Showmessage('setsockopt KeepAlive Error!'); end; klive.onoff := 1; klive.keepalivetime := 3000; klive.keepaliveinterval := 1; if WSAIoctl(IdTCPClient1.Socket.Binding.Handle, SIO_KEEPALIVE_VALS, @klive, SizeOf(TTCP_KEEPALIVE), @outKlive, SizeOf(TTCP_KEEPALIVE), @opt,0,nil) = SOCKET_ERROR then begin Showmessage('WSAIoctl KeepAlive Error!'); end; end; 客户端的异常捕捉,我是放在客户端读取服务端发送过来数据的线程里面 procedure TReadThread.Execute; var TestBuffer:TSendDataNet; begin { Place thread code here } frmmain.log('Client Begin reading...'); while permit do begin try frmmain.IdTCPClient1.ReadBuffer(TestBuffer,SizeOf(TestBuffer)); sleep(100); except on e:Exception do begin permit:=False; if frmmain.IdTCPClient1.Connected then frmmain.IdTCPClient1.Disconnect; frmmain.RzStatusPane1.Caption:='断开; frmmain.LinkTimer.Enabled:=True;//这儿启动定时器重连服务端 end; end; end; ThreadDestroy; end;