4

TCP通信にはIndyを使用しています(D2009、Indy10)。

クライアントのリクエストを評価した後、クライアントに回答を送信したいと思います。したがって、このようにTIdContextを格納します(擬似コード)

procedure ConnectionManager.OnIncomingRequest (Context : TIdContext);
begin
  Task := TTask.Create;
  Task.Context := Context;
  ThreadPool.AddTask (Task);
end;

procedure ThreadPool.Execute (Task : TTask);
begin
  // Perform some computation
  Context.Connection.IOHandler.Write ('Response');
end;

しかし、クライアントが要求と応答の送信準備ができている間のどこかで接続を終了した場合はどうなりますか?コンテキストがまだ有効かどうかを確認するにはどうすればよいですか?私は試した

if Assigned (Context) and Assigned (Context.Connection) and Context.Connection.Connected then
  Context.Connection.IOHandler.Write ('Response');

しかし、それは役に立ちません。場合によっては、プログラムがハングし、実行を一時停止すると、現在の行がif条件の行であることがわかります。

ここでは何が起きるのですか?デッド接続を使用して送信しようとしないようにするにはどうすればよいですか?

4

2 に答える 2

5

さて、私は解決策を見つけました。TIdContext を格納する代わりに、TIdTcpServer によって提供されるコンテキスト リストを使用します。

procedure ThreadPool.Execute (Task : TTask);
var
  ContextList : TList;
  Context : TIdContext;
  FoundContext : Boolean;
begin
  // Perform some computation

  FoundContext := False;
  ContextList := FIdTCPServer.Contexts.LockList;
  try
    for I := 0 to ContextList.Count-1 do
      begin
      Context := TObject (ContextList [I]) as TIdContext;
      if (Context.Connection.Socket.Binding.PeerIP = Task.ClientInfo.IP) and
         (Context.Connection.Socket.Binding.PeerPort = Task.ClientInfo.Port) then
        begin
        FoundContext := True;
        Break;
        end;
      end;
  finally
    FIdTCPServer.Contexts.UnlockList;
  end;

  if not FoundContext then
    Exit;

  // Context is a valid connection, send the answer

end;          

それは私にとってはうまくいきます。

于 2009-09-11T14:41:41.383 に答える
2

クライアントが接続を閉じた場合、クライアント マシン/ネットワーク カードが停止した場合、またはクライアントとの間で他のネットワークの問題が発生した場合は、次に接続への書き込みを試みるまで、そのことがわからない可能性があります。

ハートビートを使用できます。接続がまだ有効かどうかを確認するために、短いタイムアウトで時々クライアントにメッセージを送信します。これにより、予期しない切断が発生した場合にすぐにわかります。「CheckConnection」関数でラップして、応答を送信する前に呼び出すことができます。

于 2009-09-11T12:42:50.253 に答える