Delphi之TClientSocket和TServerSocket使用tcp keepalive心跳機制實現“斷網”、"斷電"檢測


 

開發環境: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下載

測試效果圖:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM