Search code examples
delphitcpdelphi-2009indy

Howto determine if connection is still alive with Indy?


I use Indy for TCP communication (D2009, Indy 10).

After evaluating a client request, I want to send the answer to the client. I therefore store the TIdContext, like this (pseudocode)

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;

But what if the client terminates the connection somewhere between the request and the answer being ready for sending? How can I check if the context is still valid? I tried

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

but it does not help. In some cases the program just hangs and if I pause execution I can see that the current line is the one with the if conditions.

What happens here? How can I avoid trying to send using dead connections?


Solution

  • Okay, I found a solution. Instead of storing the TIdContext I use the context list provided by 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;          
    

    That works for me.