Question

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?

Was it helpful?

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.

OTHER TIPS

If the client closes the connection, the client machine/network card dies or you have some other network problem between you and the client, you might not know about it until the next time you try to write to the connection.

You could use a heartbeat. Occasionally send a message to the client with a short timeout to see if the connection is still valid. This way, you'll know sooner if there has been an unexpected disconnect. You could wrap it in a "CheckConnection" function and call it before sending your response.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top