【问题标题】:unstable tcp receive times不稳定的 tcp 接收时间
【发布时间】:2012-01-26 22:00:34
【问题描述】:

我正在编写一个客户端,使用套接字从记录 PC (RP) 接收 EEG 数据以产生一些在线反馈。

RP 有一个通过 TCP 发送数据的服务器。数据与块一起发送,每个块都有一个标题和数据(总共是 2560 字节)。区块每 20 毫秒 (50 Hz) 发送一次。

当我运行客户端时,它会以 bursts 的形式接收数据块(例如,一个数据块持续 40ms,然后瞬间下一个数据块,0ms)。首先我认为这是因为服务器使用 Nagle 的算法并且数据包很小,可以单独发送,但是当我将块大小减小到 400 字节时,recv() 返回时间变得更加稳定(现在大约 20 毫秒。仍然一些变化,但不再爆发)。即使有 2.5k 个数据包,所需的总带宽看起来也不大:50*2560 = 128 kB/s。当我在 localhost 上同时运行客户端和服务器时,存在同样的不稳定。这里可能有什么问题?

这是(简化的)客户的代码:

# ...
# packet definitions as ctypes structures:
from protocol_defines import header, message

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((addr, port))
hdr = header() # 24 bytes
msg = message() # 2560 bytes

while True:
    s.recv_into(hdr) # this thing should return once the hdr buffer is filled
    # ... check if the message is ok ...
    s.recv_into(msg) # this thing should return once the hdr buffer is filled
    print time.time() # this is how I measure arrival times

UPD:我检查了与wireshark 的对话。问题似乎出在客户端:它仅在最后一个服务器的 [PSH, ACK] 后 40 毫秒后才发送 [ACK] 数据包(服务器几乎立即响应客户端的 [ACK])。服务器此时已经获取了 2 个数据包,因此它发送了 2 个粘合数据包。问题仍然悬而未决:(

PS:我使用的是 2.6.35 内核的 Ubuntu

【问题讨论】:

  • 我不太擅长网络编程,但我相信问题出在服务器的某个地方(并且与网络缓冲区有关)。您是否尝试过运行网络嗅探器(我可以推荐使用 wireshark)来检查网络级别的情况。
  • 可能是,但我已经尝试了两种不同的本地和远程服务器实现,并且具有相同的模式。实际上,wireshark 是个好主意,我会试试看。
  • 看起来是客户的问题。检查 UPD
  • 客户端可以根据 TCP 规范延迟其 ACK,它可以这样做,因为如果它可以捎带它在一些数据上传输,它可以节省带宽和 TCP 开销,所以它可以等待看看你是否给它一些数据发送。 srohit.tripod.com/tcpslowstart.txt。但是,在 TCP 连接“慢启动”之后,服务器不应等待每个 ACK​​ 才发送下一个数据包:srohit.tripod.com/tcpslowstart.txt

标签: python linux sockets tcp


【解决方案1】:

您可以尝试通过以下方式禁用 Nagle:

可能使用

    sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)

将帮助发送您想要的每个数据包,因为这会禁用Nagle's algorithm,就像大多数 TCP 堆栈使用它来将几个小型数据包连接在一起(并且通过 默认我相信)

正如https://stackoverflow.com/a/647835/1132184所建议的那样

【讨论】:

  • 是的,正如我在描述中所写的,我首先尝试了那个。不太好用:(
【解决方案2】:

TCP 是基于流的。永远无法保证您将收到与您发送时完全相同的所有内容。为此使用 UDP(但 UDP 不保证所有内容都到达或所有内容都以与发送相同的顺序到达。)

除此之外,按照建议禁用 nagle,因为它将发送的消息排队以减少 TCP 标头为小包增加的开销。

【讨论】:

  • 好吧,我会留下以下想法:“TCP 不适用于实时系统”
  • 取决于时间窗口必须有多小才能成为实时系统。您可能必须自己使用 UDP 重新发送数据包,这可能需要比 TCP 内置功能更长的时间。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-07
  • 1970-01-01
相关资源
最近更新 更多