2

私は3つの質問があります:

  1. 多くの接続によってIdTCPServerを破壊することは可能ですか?私は自分のアプリケーションをテストしようとしましたが、複数の接続がある場合は非常にうまく機能しますが(数日でも)、接続数が増えるとアプリケーションがアクセス違反になります。私は、データを絶えず送信する50のクライアントをシミュレートするアプリケーションを作成しました(sleep(200)のみ)。そして、この状況では、IdTCPServerは例外を出しますか?私のアプリケーションは、TidNotifyクラスとTIdSyncクラスを使用して、onExecuteイベントとmodyfiesデータベーステーブルによってクライアントから情報を取得します。クロスコネクションスレッドを保護すると思いますか?クライアントへの情報の送信はTTimerによって行われます(これは今だけです。他のスレッドに変更します)。この状況で、特別な保護またはそのようなもので十分ですか?

    type
      PClient = ^TClient;
      TClient = record
        Activity_time:TDateTime;
        AContext: TIdContext;
      end;
    ...
    list := server.Contexts.LockList;
    try
     for i := 0 to list.Count - 1 do
      with TIdContext(list[i]) do
      begin
    
        if SecondsBetween(now(), PClient(data)^.activity_time) > 6 then
        begin
          Connection.IOHandler.Close;
          Continue;
        end;
        try
          Connection.IOHandler.writeln('E:');
        Except
          Connection.IOHandler.Close;
        end;
      end;
    finally
      server.Contexts.UnlockList;
    end;
    

2.サーバーがビジー状態のときに接続を拒否する簡単な方法はありますか(データベースは複雑ではないと思います(100行、1つの接続で1行のみが変更されます)が、サーバーの安定性を維持する方法はありますか?

3.この質問が何度も繰り返されていることは知っていますが、満足のいく答えが見つかりませんでした:メッセージ例外を回避するためにアプリケーションを保護する方法:「接続が正常に閉じられました」および「接続がピアによってリセットされました」?

すべてのアドバイスをありがとう

4

1 に答える 1

3

多くの接続によってIdTCPServerを破壊することは可能ですか?

あなたは間違った質問をしています。あなたは実際にTIdTCPServerそれ自体を破壊しているのではなく、単に外部スレッドからのアイドル状態の接続を閉じているだけです。この種のロジックは、代わりにイベント内で処理できます(処理する必要があります)OnExecute。ここでは、接続にアクセスするのが最も安全です。例:

type
  PClient = ^TClient;
  TClient = record
    Activity_time: TDateTime;
    Heartbeat_time: TDateTime;
    AContext: TIdContext;
  end;

procedure TForm1.serverConnect(AContext: TIdContext);
var
  Client: PClient;
begin
  New(Client);
  Client^.Activity_time := Now();
  Client^.Heartbeat_time := Client^.Activity_time;
  AContext.Data := TObject(Client);
end;

procedure TForm1.serverDisconnect(AContext: TIdContext);
var
  Client: PClient;
begin
  Client := PClient(AContext.Data);
  AContext.Data := nil;
  if Client <> nil then Dispose(Client);
end;

procedure TForm1.serverExecute(AContext: TIdContext);
var
  Client: PClient;
  dtNow: TDateTime;
begin
  Client := PClient(AContext.Data);
  dtNow := Now();

  if SecondsBetween(dtNow, Client^.Activity_time) > 6 then
  begin
    AContext.Connection.Disconnect;
    Exit;
  end;

  if SecondsBetween(dtNow, Client^.Heartbeat_time) > 2 then
  begin
    AContext.Connection.IOHandler.WriteLn('E:');
    Client^.Heartbeat_time := dtNow;
  end;

  if AContext.Connection.IOHandler.InputBufferIsEmpty then
  begin
    if not AContext.Connection.IOHandler.CheckForDataOnSource(100) then
      Exit;
  end;

  // process incoming data as needed ...

  Client^.Activity_time := Now();
end;

サーバーがビジー状態のときに接続を拒否する簡単な方法はありますか(私のデータベースは複雑ではないと思います(100行、1つの接続で1行だけが変更されます)が、サーバーの安定性を維持する方法はここにありますか?

現在のアーキテクチャでは、接続の受け入れを拒否することはできません。サーバーに接続を通常どおり受け入れさせ、必要に応じて受け入れられた接続を閉じることができます。OnConnectイベントでこれを行うか、サーバーのMaxConnectionプロパティをゼロ以外の低い数値に設定して、サーバーが新しいTIdContextオブジェクトやスレッドを作成するリソースを無駄にすることなく、新しい接続を自動的に切断できるようにすることができます。

もう1つのオプションはStopListening()、サーバーがビジーのときにサーバーのメソッドを呼び出して、新しい接続がサーバーに到達できなくなるようにし、StartListening()新しいクライアントを再度受け入れる準備ができたらサーバーのメソッドを呼び出すことです。私はまだ実際にそれを試していませんが、すでに接続している既存のクライアントは影響を受けないはずです。

この質問が何度も繰り返されていることは知っていますが、満足のいく答えが見つかりませんでした。メッセージの例外を回避するためにアプリケーションを保護する方法:「接続が正常に閉じられました」および「接続がピアによってリセットされました」?

あなたはそれらを避けるべきではありません。それらを起こさせてください、それらは通常のエラーです。それらがサーバーのイベント内で発生している場合は、サーバーに通常どおりに処理させてください。それがTIdTCServer使用されるように設計されている方法です。タイマーなど、サーバーのイベントの外部で発生している場合は、ソケット操作をtry/exceptブロックにラップして次に進みます。

于 2013-01-02T18:17:53.623 に答える