【发布时间】: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