本文整理自网络,侵删。
开发环境:Delphi7
测试环境:WinXP,Win7 32bit,Win7 64bit
使用TClientSocket和TServerSocket实现TCP长连接通讯,经常因为断电断网等原因导致出现一些死连接。
解决方法是客户端和服务端都定时发送心跳包。
具体实现如下:
TClientSocket和TServerSocket均使用非阻塞模式
1、定义心跳常量和KeepAlive 数据结构
复制代码//定义心跳常量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;复制代码2、引用WinSock,WinSock2
3、写一个方法来使用setsockopt,WSAIoctl设置心跳包参数
复制代码procedure TForm1.setKeepAlive(Socket: TCustomWinSocket);var opt:Integer; klive, outKlive: TTCP_KEEPALIVE; i,j:integer; OptVal: DWORD;begin opt := 1; //需引用WinSock.pas if setsockopt(Socket.SocketHandle,SOL_SOCKET, SO_KEEPALIVE, PAnsiChar(@opt), SizeOf(opt)) = SOCKET_ERROR then begin showInfo(Format('WinSock Error %d', [WSAGetLastError()])); end; klive.onoff := 1; klive.keepalivetime := 5000; klive.keepaliveinterval := 1; //需引用WinSock2.pas if WSAIoctl(Socket.SocketHandle, SIO_KEEPALIVE_VALS, PAnsiChar(@klive), SizeOf(TTCP_KEEPALIVE), PAnsiChar(@outKlive), SizeOf(TTCP_KEEPALIVE), @opt,0,nil) = SOCKET_ERROR then begin showInfo(Format('WinSock Error %d', [WSAGetLastError()])); end;
end;复制代码4、在TClientSocket和TServerSocket的连接事件中调用设置心跳
procedure TForm1.ServerSocket1ClientConnect(Sender: TObject; Socket: TCustomWinSocket);begin showInfo('ServerSocket1ClientConnect-' + Socket.RemoteAddress + ':' + IntToStr(Socket.RemotePort)); setKeepAlive(Socket); //设置socket心跳,以便清除死链接end;经测试,采用以上方法,可以检测到把网线断网情况
测试demo下载:
测试效果图:
来源:https://www.cnblogs.com/tc310/p/10886086.html
相关阅读 >>
Delphi twebbrowser 响应回车键(ewb响应正常,无需额外代码)
Delphi trestclient + trestrequest + trestresponse
更多相关阅读请进入《Delphi》频道 >>