【问题标题】:Terminate an inactive socket connection from TIdTCPServer终止来自 TIdTCPServer 的非活动套接字连接
【发布时间】:2010-03-04 00:41:28
【问题描述】:

我们有一个应用程序,它使用 Delphi 2007 附带的 Indy 10.1.1 组件侦听传入的 TCP 请求。

有时我们会收到不是来自我们的客户端应用程序的传入连接。通常,会发生以下两种情况之一:1) 客户端在接收到任何数据之前终止连接,或 2) 接收到我们不期望的数据并且我们手动终止连接。

但是,我们收到了未接收到数据的连接,并且似乎会持续存在,直到客户端从其端终止连接。

如果在指定的时间后没有收到数据,有没有办法终止与服务器的这种连接?

【问题讨论】:

    标签: delphi tcp indy


    【解决方案1】:

    在您的 OnExecute 事件处理程序中,跟踪从客户端收到最后一个良好数据的时间。使用连接的 ReadTimeout 属性,您可以定期使挂起的读取操作超时,以便检查客户端是否有一段时间没有发送数据,如果是,则断开连接。

    【讨论】:

    • 这正是我想要的。我知道客户端有一个 ReadTimeout 属性,但我没有意识到连接的 IOHandler 有。谢谢。
    【解决方案2】:

    另存为 killthread.pas

    unit killthread;
    
    interface
    
    uses
      Classes, IdTCPServer, IdTCPClient, IdContext, Types, SyncObjs;
    
    type
      TKillThread = class(TThread)
      private
        FContext: TIdContext;
        FInterval: DWORD;
        FEvent: TEvent;
      protected
        procedure Execute; override;
      public
        constructor Create(AContext: TIdContext; AInterval: DWORD); overload;
        destructor Destroy; override;
        procedure Reset;
        procedure Stop;
      end;
    
    implementation
    
    { TKillThread }
    
    constructor TKillThread.Create(AContext: TIdContext; AInterval: DWORD);
    begin
      FContext := AContext;
      FInterval := AInterval;
      FEvent := TEvent.Create(nil, False, False, '');
      inherited Create(False);
    end;
    
    destructor TKillThread.Destroy;
    begin
      FEvent.Free;
      inherited Destroy;
    end;
    
    procedure TKillThread.Reset;
    begin
      FEvent.SetEvent;
    end;
    
    procedure TKillThread.Stop;
    begin
      Terminate;
      FEvent.SetEvent;
      WaitFor;
    end;
    
    procedure TKillThread.Execute;
    begin
      while not Terminated do
      begin
        if FEvent.WaitFor(FInterval) = wrTimeout then
        begin
          FContext.Connection.Disconnect;
          Exit;
        end;
      end;
    end;
    
    end.
    

    然后在服务器端执行此操作:

    procedure TYourTCPServer.OnConnect(AContext: TIdContext);
    begin
      AContext.Data := TKillThread.Create(AContext, 120000);
    end;
    
    procedure TYourTCPServer.OnDisconnect(AContext: TIdContext);
    begin
      TKillThread(AContext.Data).Stop;
    end;
    
    procedure TYourTCPServer.OnExecute(AContext: TIdContext);
    begin
      if AContext.Connection.Connected then
      begin
        TKillThread(AContext.Data).Reset;
        // your code here
      end;
    end;
    

    【讨论】:

    • 如果服务器连接了很多客户端,这有点矫枉过正,因为您正在使用的运行线程和内核对象的数量增加一倍。
    【解决方案3】:

    我有类似的问题,我用的是delphi7+Indy9。

    和我的解决方案: 在 TIdTCPServer 事件 onConnect 中,我喜欢这样

    procedure Tf_main.ServerHostConnect(AThread: TIdPeerThread);
    begin
      //code something
    
      //mean AThread will do Disconnected  if Client no activity ( send receive ) on interval...) 
      AThread.Connection.ReadTimeout := 300000;  //5 minutes..
    
      //code something
    end;
    

    也许在 Indy10 上你可以做类似的事情

    【讨论】:

      【解决方案4】:

      您应该可以拨打(TIdTCPConnection).Disconnect

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-12-10
        • 1970-01-01
        • 2019-10-17
        • 2011-06-13
        • 1970-01-01
        相关资源
        最近更新 更多