TCP 接收时间不稳定
我正在编写一个客户端,使用套接字从记录 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以尝试通过以下方式禁用 Nagle:
正如 https://stackoverflow.com/a/647835/1132184 中所建议的
You could try disabling Nagle by:
as has been suggested in https://stackoverflow.com/a/647835/1132184
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.