串行到以太网 (TCP) 字节传输的显着延迟?

Significant delay for serial to ethernet (TCP) byte transmission?

我正在尝试使用我在 Raspberry Pi 上开发并用 C++ 编码的设备测量通过以太网和串行端口传输数据的往返时间。我编写了一个 C# 程序,它一次向 Raspberry Pi 发送一个字节(波特率 = 9600)并测量接收该字节所需的时间。在每个场景中,我都会在实际测试开始之前建立 UDP 或 TCP 连接。

这是我的四种情况:

  1. 通过以太网发送一个字节并通过以太网接收回来
  2. 通过以太网发送一个字节并通过串口接收回来
  3. 通过串口发送一个字节并通过以太网接收回来

对于测试 4,未使用 Raspberry Pi 设备;而是C#测试程序的电脑串口是直连的

  1. 通过串口发送一个字节并通过串口接收回来

对于每个 "Ethernet" 部分,测试了 UDP 和 TCP,这里是平均结果(超过数千个数据点 - 10 次试验,每次 1000 点):

  1. 一个。 UDP 到 UDP:<1 毫秒
    b. TCP 到 TCP:<1 毫秒
  2. 一个。 UDP 到串口:~5ms
    b. TCP 到串口:~5ms
  3. 一个。串行到 UDP:~5ms
    b.串行到 TCP:~62ms

  4. 串行到串行:~6ms

我很困惑为什么 Serial to TCP 与其他配置相比有这么大的延迟。此外,发送的第一个字节似乎总是有 4-5 毫秒的往返时间。之后,所有字节的 RTT 约为 62 毫秒。任何人都可以解释一下或指出一个好的资源吗?它与流水线或串行和以太网之间的瓶颈有关吗?如果是这样,为什么我没有看到与串行 - UDP 相同的现象?

UDP 和 TCP 的代码在结构上基本相同。如果您需要查看代码,我也可以上传。


更新: 我仍然无法解决这个问题。我试图在 C++ RPi 服务器中将 setsockopt 禁用为 TCP_NODELAY,但这并没有真正改变时间。我也研究过使用 NTP 在笔记本电脑和 RPi 之间同步时间,但我 运行 也遇到了很多问题。例如,C# 上的 UTC 毫秒分辨率似乎不够高。此外,我在与我的笔记本电脑和 Rpi 同步时遇到问题,所以我不想走那条路。任何建议表示赞赏!

您的用例是以最短延迟发送单个字节的 TCP。这是一个应该针对您的用例优化 TCP 的简单协议:

首先,不要禁用 Nagle。其次,每次接收方收到一些数据时,它应该发送一个回复字节。发送方应收到回复字节并丢弃它。

接收器应尝试一次至少接收 64 个字节。不管它实际接收到多少字节,它都应该发送一个字节作为回复。

这应该通过允许 ACK 搭载在回复字节上来稳定您的延迟。在绝大多数情况下,接收方一次接收一个字节,但您需要一种从网络或 CPU 问题中恢复的方法,而不是一种会被它们中断并逐渐显示更糟糕行为的方案。

发件人永远不需要等待回复字节。它可以随时发送。