终止来自 TIdTCPServer 的非活动套接字连接

发布于 2024-08-23 13:00:16 字数 257 浏览 6 评论 0原文

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

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

但是,我们收到的连接没有收到任何数据,并且似乎一直持续到客户端从其一端终止连接为止。

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

We have an application which listens for incoming TCP requests using the Indy 10.1.1 components that ship with Delphi 2007.

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.

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

热情消退 2024-08-30 13:00:16

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

In your OnExecute event handler, keep track of when the last good data was received from the client. 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.

为你鎻心 2024-08-30 13:00:16

将其保存为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;

Save this as 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;
雨的味道风的声音 2024-08-30 13:00:16

我有类似的问题,我用的是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 上你可以做类似的事情

i have similiar problem, i used delphi7+Indy9.

and my solution:
in TIdTCPServer event onConnect, i do like this

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

天煞孤星 2024-08-30 13:00:16

您应该能够调用(TIdTCPConnection).Disconnect

You should be able to call (TIdTCPConnection).Disconnect.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文