Завершить неактивное соединение с сокетом из TIdTCPServer - PullRequest
2 голосов
/ 04 марта 2010

У нас есть приложение, которое прослушивает входящие TCP-запросы, используя компоненты Indy 10.1.1, которые поставляются с Delphi 2007.

Иногда мы получаем входящие соединения, которые не из нашего клиентского приложения. Как правило, происходит одно из двух: 1) соединение прерывается клиентом до получения каких-либо данных, или 2) получение данных, которых мы не ожидаем, и мы вручную разрываем соединение.

Однако мы получили соединения, в которых данные не получены и сохраняются до тех пор, пока клиент не завершит соединение с их конца.

Есть ли способ разорвать такое соединение с сервером, если по истечении указанного времени данные не получены?

Ответы [ 4 ]

3 голосов
/ 04 марта 2010

В обработчике событий OnExecute отслеживайте, когда последние хорошие данные были получены от клиента. Используя свойство ReadTimeout соединения, вы можете периодически приостанавливать ожидающие операции чтения, чтобы вы могли проверить, не отправлял ли клиент какое-то время, а затем отключить его.

1 голос
/ 08 мая 2010

У меня похожая проблема, я использовал 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 вы можете сделать подобное

1 голос
/ 04 марта 2010

Сохраните это как 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;
0 голосов
/ 04 марта 2010

Вы должны быть в состоянии звонить (TIdTCPConnection).Disconnect.

...