TCP 接收时间不稳定

发布于 2024-12-22 10:58:56 字数 1208 浏览 0 评论 0原文

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

RP 有一个通过 TCP 发送数据的服务器。数据以块的形式发送,每个块都有一个标头和数据(总共 2560 字节)。这些块每 20 毫秒 (50 Hz) 发送一次。

当我运行客户端时,它会突发接收块(例如,一个块40ms,然后立即接收下一个块,0ms)。首先,我认为这是因为服务器使用 Nagle 算法,并且数据包很小,无法单独发送,但是当我将块大小减少到 400 字节时,recv() 返回时间变得更加稳定(现在约为 20 毫秒)。一些变化,但不再爆发)。即使有 2.5k 数据包,所需的总带宽看起来也并不大: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

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

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

I'm writting a client using socket to receive EEG data from a recording PC (RP) to produce some online feedback.

The RP has a server which sends the data over TCP. The data is being sent with blocks, each having a header and data (alltogether is 2560 bytes). The blocks are sent every 20 ms (50 Hz).

When I run the client, it receives the blocks in bursts (e.g. one block for 40ms then next one instantaniously, 0ms). First I thought this is because the server uses Nagle's algorithm and packets are small to be sent individually, but when I reduce the block size to, say, 400 bytes, the recv() returning time becomes much more stable (around 20ms now. Still some variation but no bursts anymore). Even with the 2.5k packets, the total required bandwidth doesn't look large: 50*2560 = 128 kB/s. Same unstability is present when I'm running both client and server on localhost. What might be the problem here?

Herer's the (simplified) client's code:

# ...
# 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: I checked the conversation with wireshark. The problem seems to be in the client: it sends [ACK] packets only after 40ms since the last server's [PSH, ACK] (the server responds almost instantaneously on client's [ACK]). The server has already acquired 2 packets by the time, so it sends 2 glued packets. The question remains opened :(

PS: I'm using Ubuntu with 2.6.35 kernel

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦途 2024-12-29 10:58:56

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

可能使用

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

将帮助按照您想要的方式发送每个数据包,因为这会禁用Nagle的算法,和大多数人一样
TCP 堆栈使用它来将多个小数据包连接在一起(并且由
默认我相信)

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

You could try disabling Nagle by:

Possibly using

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

will help send each packet as you want it as this disables Nagle's algorithm, as most
TCP stacks use this to join several packets of small-sized data together (and is on by
default I believe)

as has been suggested in https://stackoverflow.com/a/647835/1132184

空气里的味道 2024-12-29 10:58:56

TCP 是基于流的。无法保证您收到的所有内容均与您发送的内容完全一致。为此使用 UDP(但 UDP 不保证所有内容都到达或所有内容都按照与发送相同的顺序到达。)

除此之外,请按照建议禁用 nagle,因为它会对发送的消息进行排队以减少 TCP 标头添加的开销对于小包装。

TCP is stream based. There is never a guarantee that you will receive everything exactly as you sent it. Use UDP for that (but UDP does not guarantee that everything arrives or that everything arrives in the same order as being sent.)

Other than that, disable nagle as suggested, since it queues up sent messages to reduce the overhead that the TCP header adds for small packages.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文