简体   繁体   English

终止TIdTCPServer的无效套接字连接

[英]Terminate an inactive socket connection from TIdTCPServer

We have an application which listens for incoming TCP requests using the Indy 10.1.1 components that ship with Delphi 2007. 我们有一个应用程序,它使用Delphi 2007附带的Indy 10.1.1组件侦听传入的TCP请求。

Occassionally we receive incoming connections which are not from our client application. 有时我们会收到来自客户端应用程序的传入连接。 Typically, one of two things happens: 1) the connection is terminated by the client before any data is received, or 2) data is received which we're not expecting and we manually terminate the connection. 通常,发生以下两种情况之一:1)客户端在接收到任何数据之前终止了连接,或者2)接收到了我们不期望的数据,我们手动终止了连接。

However, we've received connections where no data is received and appear to persist until the client terminates the connection from their end. 但是,我们收到的连接中没有接收到任何数据,并且看起来一直存在,直到客户端从其末端终止连接为止。

Is there a way to terminate such a connection from the server if no data is received after a specified amount of time? 如果在指定的时间段内未收到任何数据,是否可以终止与服务器的这种连接?

In your OnExecute event handler, keep track of when the last good data was received from the client. 在您的OnExecute事件处理程序中,跟踪何时从客户端收到了最后的正确数据。 Using the connection's ReadTimeout property, you can timeout pending read operations periodically so you can check if the client has not sent data for awhile, and if so then disconnect it. 使用连接的ReadTimeout属性,可以定期使挂起的读取操作超时,以便可以检查客户端是否有一段时间没有发送数据,如果是,则断开连接。

Save this as killthread.pas 将此另存为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.

Then do this on the server side: 然后在服务器端执行此操作:

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;

i have similiar problem, i used delphi7+Indy9. 我有类似的问题,我用过delphi7 + Indy9。

and my solution: in TIdTCPServer event onConnect, i do like this 和我的解决方案:在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;

maybe on Indy10 you can do similiar like that 也许在Indy10上您可以像这样

您应该可以调用(TIdTCPConnection).Disconnect

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM