delphi - 当客户端连接到 TIdTCPServer 时线程数增加

标签 delphi indy indy10 delphi-10.1-berlin tcpserver

我有一个使用 Delphi 10.1 创建的 64 位服务器应用程序,在这个应用程序中我有一个 TIdTCPServer 组件。

当客户端连接时,线程计数会增加,而当客户端断开连接时,线程计数不会减少。此问题发生在 Windows Server 计算机上。我没有处理 OnConnectOnDisconnect 事件中的任何代码。下面是我的 OnExecute 方法:

  try
      if not AContext.Connection.IOHandler.InputBufferIsEmpty then
      begin
        AContext.Connection.IOHandler.InputBuffer.ExtractToBytes(ReceivedIDBytes.PointerMessage.tyTIDBytes) ;
        ReceivedIDBytes.ClientSocket := AContext.Connection;
        MessageProcessorThread.ProcessMessageQueue.Enqueue(ReceivedIDBytes);
        IndySleep(50);
      end;
      IndySleep(5);
  except
  end;

我应该使用 Application.ProcessMessages() 来解决此问题吗?

由于线程数增加,我需要定期重新启动服务器应用程序。

最佳答案

不要吞下异常! Indy 使用异常来报告套接字断开连接/错误等情况(EIdConnClosedGraceouslyEIdSocketError 等)。 TIdTCPServer 在内部处理其事件处理程序引发的未捕获异常,以了解何时清理管理已接受套接字的线程。通过吞咽异常,您将阻止 TIdTCPServer 正确执行清理操作。

如果您出于某种原因需要捕获异常(清理、日志记录等1),则至少应该重新引发从 EIdException 派生的任何异常。让 TIdTCPServer 处理 Indy 生成的异常,尤其是由于套接字断开连接而发生的异常。

1:考虑使用 TIdTCPServer.OnException 事件来代替。

try
  if not AContext.Connection.IOHandler.InputBufferIsEmpty then
  begin
    AContext.Connection.IOHandler.InputBuffer.ExtractToBytes(ReceivedIDBytes.PointerMessage.tyTIDBytes);
    ReceivedIDBytes.ClientSocket := AContext.Connection;
    MessageProcessorThread.ProcessMessageQueue.Enqueue(ReceivedIDBytes);
    IndySleep(50);
  end;
  IndySleep(5);
except
  on E: Exception do
  begin
    ...
    if E is EIdException then
      raise; // <-- add this!
  end;
end;

我还建议删除 IndySleep() 调用。您实际上并不需要它们,让 Indy 在等待新数据到达时为您休眠:

try
  if AContext.Connection.IOHandler.InputBufferIsEmpty then
  begin
    // the next call sleeps until data arrives or the specified timeout elapses...
    AContext.Connection.IOHandler.CheckForDataOnSource(55);
    AContext.Connection.IOHandler.CheckForDisconnect;
    if AContext.Connection.IOHandler.InputBufferIsEmpty then Exit:
  end;
  AContext.Connection.IOHandler.InputBuffer.ExtractToBytes(ReceivedIDBytes.PointerMessage.tyTIDBytes);
  ReceivedIDBytes.ClientSocket := AContext.Connection;
  MessageProcessorThread.ProcessMessageQueue.Enqueue(ReceivedIDBytes);
except
  on E: Exception do
  begin
    ...
    if E is EIdException then
      raise;
  end;
end;

或者,使用 TIdIOHandler.ReadBytes() 而不是直接使用 TIdBuffer.ExtractToBytes():

try
  SetLength(ReceivedIDBytes.PointerMessage.tyTIDBytes, 0);
  // the next call sleeps until data arrives or the IOHandler.ReadTimeout elapses...
  AContext.Connection.IOHandler.ReadBytes(ReceivedIDBytes.PointerMessage.tyTIDBytes, -1, False);
  if Length(ReceivedIDBytes.PointerMessage.tyTIDBytes) > 0 then
  begin
    ReceivedIDBytes.ClientSocket := AContext.Connection;
    MessageProcessorThread.ProcessMessageQueue.Enqueue(ReceivedIDBytes);
  end;
except
  on E: Exception do
  begin
    ...
    if E is EIdException then
      raise;
  end;
end;

关于delphi - 当客户端连接到 TIdTCPServer 时线程数增加,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57364577/

相关文章:

delphi - 我们如何连接网站?收到 SSL 错误 1409442E

delphi - Delphi 中的微 Controller 编程

c# - Delphi 相当于 C# 的 DataGridView

delphi - 如何修补TSpinEdit以使用Vista/Win7视觉样式?

multithreading - 使用 Omni Thread Library 在 Delphi 中异步获取函数结果

delphi - TidHTTP 错误处理

delphi - 从 GMail 的 "Sent items"文件夹获取电子邮件 header

openssl - 如何使 Indy OpenSSL 与大多数服务器兼容

delphi - 如何检测服务器是否使用 TIdTCPClient 响应请求?

delphi - 更新到最新的 Indy TCP 库版本