You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi Indy10 TIdTCPServer Linux环境下客户端断开失败问题咨询

根因分析
  • Indy10在Windows和Linux平台的底层IO模型实现不一致:Windows采用IOCP完成端口模型,异常断开的连接会被系统自动通知Indy回收对应TIdContext;Linux采用per-connection线程+select模型,无RST包的异常断开场景下,默认的Disconnect调用不会触发Context队列的移除逻辑,导致条目残留
  • TIdTCPConnection内置的FConnectionHandle临界区在Linux下基于pthread_mutex实现,无获取超时机制:如果在非Indy工作线程(如自定义超时检测线程)中直接调用Binding.CloseSocket,会和Indy内部OnExecute/OnDisconnect事件的执行线程抢占临界区,触发死锁导致调用无响应,多次重复调用会触发临界区未定义行为,直接导致进程崩溃无日志
解决方案

1. 调整断开逻辑的执行上下文,避免跨线程操作

给自定义TDTBClient类新增待断开标记属性,外部超时检测线程仅负责修改该标记,所有断开操作统一放到Indy的OnExecute事件中执行,从根源上避免临界区抢占问题:

// 自定义TDTBClient类新增属性
type
  TDTBClient = class
  public
    NeedDisconnect: Boolean;
    // 其他原有属性
  end;

2. 实现线程安全的断开逻辑

在OnExecute事件的循环头部优先检测断开标记,在Indy自身的工作线程中执行断开,Indy会自动完成Context回收:

procedure TYourServerForm.IdTCPServerExecute(AContext: TIdContext);
var
  LClient: TDTBClient;
begin
  LClient := TDTBClient(AContext.Data);
  // 优先检测断开标记
  if LClient.NeedDisconnect then
  begin
    AContext.Connection.Disconnect(False); // 跳过优雅断开,直接终止连接
    Exit; // 退出事件后Indy会自动从Context列表移除当前条目
  end;
  // 原有业务逻辑
end;

3. 修复服务端关闭卡死问题

关闭服务端前不要直接设置Active := False,先主动清理所有存活连接,Linux下增加回收等待时间:

procedure TYourServerForm.StopServer;
var
  I: Integer;
  LContextList: TList;
begin
  if not IdTCPServer.Active then Exit;

  LContextList := IdTCPServer.Contexts.LockList;
  try
    for I := 0 to LContextList.Count - 1 do
    begin
      TIdContext(LContextList[I]).Connection.Disconnect(False);
    end;
  finally
    IdTCPServer.Contexts.UnlockList;
  end;

  Sleep(150); // Linux下预留150ms等待Context回收完成,避免残留条目卡主关闭流程
  IdTCPServer.Active := False;
end;

4. 开启TCP层保活自动清理死连接

在OnConnect事件中为每个新连接开启TCP KeepAlive,从内核层面自动识别无响应的死连接,减少手动断开的需求:

procedure TYourServerForm.IdTCPServerConnect(AContext: TIdContext);
begin
  // 开启保活:30秒无流量开始发保活包,每3秒发一次,累计3次失败判定为死连接
  AContext.Connection.Socket.Binding.SetKeepAliveValues(True, 30000, 3000);
  // 绑定自定义TDTBClient实例
  AContext.Data := TDTBClient.Create;
end;

5. 可选优化:升级Indy组件版本

Delphi 10.4自带的Indy10存在多个Linux平台专属的临界区、Context回收bug,可手动升级到Indy官方最新主干版本,已修复多数已知Linux兼容性问题。


内容的提问来源于stack exchange,提问作者Bart Kindt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 14:24:01