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

Delphi 12.1+Indy10与FreeRTOS/LwiP通信超时及卡顿问题咨询

问题解答

Q1:为何两种读取方法结果不同?

两种读取方法的核心差异在于Indy的超时机制和数据读取逻辑:

  • 方法1应该是直接调用Read()这类带超时参数的接口,这类接口会严格按照设定的超时时间等待完整数据,一旦超时窗口内未收到足够数据就抛出ReadTimeout异常。如果异常处理逻辑存在疏漏(比如未正确释放Socket资源就尝试重连),会导致资源泄漏,线程被阻塞在无效的Socket句柄上,无法发起新连接。
  • 方法2大概率是CheckForDataOnSource()轮询+手动读取的组合,这种方式的超时仅针对单次轮询(比如你设置的250ms),但如果后续读取数据时未做整体超时控制,就会出现:轮询到有数据后,若网络卡顿导致数据分批到达,线程会一直等待剩余数据,整体时长远超设定的单次超时,看起来像“卡顿”,但不会触发Indy的ReadTimeout异常——因为根本没用到带超时的读取接口。

Q2:输入缓冲区是否存在字节限制导致内存问题与超时?

Indy的默认输入缓冲区(InputBuffer)无硬性字节限制,是动态扩容的,但LwiP端有默认的TCP接收缓冲区大小(通常为几KB到几十KB)。如果服务器端LwiP缓冲区满,会触发TCP流量控制(滑动窗口),客户端发送的数据会被阻塞;反过来如果客户端接收缓冲区处理不及时,也会导致服务器端发送卡顿,最终引发超时。
另外,若读取逻辑未及时清空Indy的InputBuffer,堆积的数据会占用内存,但一般不会直接导致超时,更多是引发内存泄漏或读取逻辑混乱。你可以通过FClient.Socket.InputBuffer.Size监控缓冲区大小,排查是否存在数据堆积。

Q3:方法2无超时却卡顿,是否为网络延迟?为何未触发超时?

不是单纯的网络延迟,核心是超时逻辑不匹配:

  • CheckForDataOnSource(250)仅负责检查“是否有数据到达”的超时,一旦检测到有数据,后续调用Read()时若未指定超时参数,Indy会一直等待数据,直到收到足够字节或连接断开。所以当数据分批到达(比如网络抖动导致服务器端发送的135172字节拆成多包,中间间隔很长),线程就会卡在Read()上,总时长远超250ms,但因为没给Read()设置超时,自然不会抛出超时异常。
  • 另外要排查LwiP的发送逻辑:FreeRTOS下如果服务器端的发送线程被高优先级任务抢占,也会导致数据发送延迟,客户端这边就会出现长时间等待剩余数据的情况。

Q4:客户端通过FClient.Socket.CheckForDataOnSource(250)等待,且单次发4096字节、收135172字节,为何流量高达客户端→服务器70KB/s、服务器→客户端2315KB/s?

核心是通信循环的频率和实际数据收发的批次:

  • 你所说的“单次发4096字节、收135172字节”是单次请求的数据包大小,但如果线程在循环执行“发→收→发→收”的逻辑,且循环间隔极短(比如收完数据立刻发送下一个请求),实际每秒的请求次数会很多。比如:70KB/s ÷ 4KB ≈ 17次/秒,2315KB/s ÷ 132KB ≈ 17次/秒,刚好匹配这个频率。
  • 另外要检查是否存在重复发送的逻辑:比如方法1触发超时后,异常处理代码未正确终止当前请求就重复发送数据;或者CheckForDataOnSource()返回False时,逻辑错误地重新发送请求,导致无效重复发包,拉高了流量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 07:08:10