indy的服务器端和客户端心跳处理

服务端的心跳处理(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;

你可能感兴趣的:(服务器)