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

Delphi跨平台Socket安卓客户端连接离线服务器卡顿问题咨询

问题根因

  • 你使用的System.Net.Socket.TSocket的Connect方法默认是阻塞同步调用,当服务端离线时,调用会卡在操作系统内核的TCP连接超时逻辑中,这个过程不受应用层的线程终止标记、对象释放操作控制,强制释放还在阻塞调用中的Socket对象会直接触发内存访问错误。
  • 你现有的线程嵌套逻辑(FThread里又开RThread)、Sleep硬等500ms的逻辑也有逻辑漏洞,会导致状态判断混乱。

修复方案

1. 改用带超时的非阻塞连接逻辑

使用Connect的超时重载,发起连接后最多等待指定时长,超时就主动放弃,不会一直卡住。

2. 简化线程模型,单线程处理连接+重试+收消息逻辑

不需要开两层匿名线程,单个工作线程循环处理:连接失败就间隔几秒重试,连接成功就处理收消息逻辑,断开后自动回到重连流程,线程终止信号触发时直接退出循环即可。

3. 线程安全的状态管理,避免跨线程直接操作Socket对象

用事件信号控制线程退出,不要在主线程销毁阶段直接释放还在工作线程中使用的Socket对象。

修复后参考代码

uses
  System.SysUtils, System.Net.Socket, System.SyncObjs;

var
  Form1: TForm1;
  FClientSocket: TSocket;
  FWorkThread: TThread;
  FConnected: Boolean;
  FTerminateFlag: TEvent; // 用事件信号控制线程退出,响应更及时

procedure TForm1.FormCreate(Sender: TObject);
begin
  FConnected := False;
  FTerminateFlag := TEvent.Create(nil, False, False, '');
  // 单工作线程处理所有连接、重连、收消息逻辑
  FWorkThread := TThread.CreateAnonymousThread(procedure
  var
    WaitResult: TWaitResult;
    ConnectSuccess: Boolean;
  begin
    while not FWorkThread.Terminated do
    begin
      // 等待退出信号,间隔3秒发起一次重连
      WaitResult := FTerminateFlag.WaitFor(3000);
      if WaitResult = wrSignaled then Break;

      if FConnected then Continue; // 已连接则跳过重连逻辑

      try
        FClientSocket := TSocket.Create(TSocketType.TCP, TProtocolType.IP);
        try
          // 核心:带2秒超时的连接逻辑,超时未成功直接放弃
          ConnectSuccess := FClientSocket.Connect('192.168.1.155', 4851, 2000);
          if ConnectSuccess then
          begin
            FConnected := True;
            // 连接成功后进入收消息循环
            while FConnected and not FWorkThread.Terminated do
            begin
              // 收消息同样加超时,避免一直阻塞
              if FClientSocket.CanRead(1000) then
              begin
                // 此处添加你的消息处理逻辑
                // 如果接收失败/抛出异常,将FConnected设为False即可触发重连
              end;
            end;
          end;
        finally
          // 退出当前逻辑时安全释放Socket
          FConnected := False;
          FreeAndNil(FClientSocket);
        end;
      except
        // 捕获连接、接收阶段的所有异常,避免线程崩溃
        FConnected := False;
        FreeAndNil(FClientSocket);
      end;
    end;
  end);
  FWorkThread.FreeOnTerminate := False;
  FWorkThread.Start;
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  // 先触发退出信号,唤醒等待中的工作线程
  if Assigned(FTerminateFlag) then
    FTerminateFlag.SetEvent;

  // 安全终止工作线程
  if Assigned(FWorkThread) then
  begin
    FWorkThread.Terminate;
    FWorkThread.WaitFor;
    FreeAndNil(FWorkThread);
  end;

  // 释放事件对象
  FreeAndNil(FTerminateFlag);
end;

内容的提问来源于stack exchange,提问作者Jacck Cooper

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 19:06:00