不稳定的TCP接收时间

3 投票
2 回答
1204 浏览
提问于 2025-04-17 08:54

我正在写一个客户端,通过套接字从一个记录电脑(RP)接收脑电图(EEG)数据,以便提供一些在线反馈。

这个记录电脑上有一个服务器,它通过TCP协议发送数据。数据是以块的形式发送的,每块都有一个头部和数据(总共2560字节)。这些数据块每20毫秒发送一次(也就是50赫兹)。

当我运行客户端时,它接收到的数据块是以突发的方式到达的(比如说,先接收到一个块用了40毫秒,然后下一个块几乎是立刻到达,0毫秒)。我开始以为这是因为服务器使用了Nagle算法,导致数据包太小,不能单独发送,但当我把块的大小减到400字节时,recv()的返回时间变得更加稳定(现在大约是20毫秒。虽然还有一些波动,但不再是突发了)。即使是2.5千字节的数据包,总带宽需求看起来也不大:50*2560 = 128 kB/s。在我同时在本地运行客户端和服务器时,也出现了同样的不稳定情况。这里可能是什么问题呢?

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

# ...
# 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

更新:我用wireshark检查了数据传输情况。问题似乎出在客户端:它在上一个服务器的[PSH, ACK]之后要等40毫秒才发送[ACK]数据包(服务器几乎是立刻对客户端的[ACK]做出回应)。到那时,服务器已经收到了2个数据包,所以它发送了2个合并的数据包。这个问题仍然没有解决 :(

附注:我使用的是Ubuntu,内核版本是2.6.35

2 个回答

1

你可以尝试通过以下方式来关闭Nagle算法:

可能可以使用

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

这样做可以让你按自己的需求发送每个数据包,因为这会关闭Nagle算法。大多数TCP协议的实现都会默认开启这个算法,它的作用是把几个小数据包合并成一个发送。

这个建议可以参考在这个链接中找到的内容。

0

TCP是一种基于流的协议。这意味着你发送的数据不一定会完全按照你发送的顺序到达接收方。想要确保数据准确到达,可以使用UDP(不过UDP也不能保证所有数据都能到达,或者到达的顺序和发送时一样)。

除此之外,建议关闭Nagle算法,因为它会把发送的小消息排队,以减少TCP头部带来的额外开销。

撰写回答