我有一个在Python中使用套接字构build的TCP服务器。 我正在构build的应用程序是时间敏感的,所以数据的完整性很重要,因此我们需要TCP。 带宽非常低。
还有一个客户端每隔50毫秒向服务器请求一次数据。 如果服务器没有数据或实际需要的数据,客户端会收到OK消息。
每当客户端向服务器发出请求时,它就发送一个5字节的帧(不包括来自IP和TCP的40个额外字节)。 另一方面,服务器或者以5字节的帧(在大多数情况下)或者大于70字节的帧(通常为每秒)
两边的sockets都是这样设置的:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) # this line is excluded in client's case sock.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, 8192) sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) sock.settimeout(0.5)
一切运行良好在本地networking(没有滞后),但每当我连接到公共IP(我是端口转发)的服务器,它滞后了很多。 滞后可能高达15秒(在那一刻它超时),这是令人难以置信的多。 RTT大部分时间停留在200-210毫秒。 在WireShark上,我可以看到有很多(伪)重传和dup ACK。
我能做什么? 我已经禁用了Nagle的algorithm,但是还没有成功。
我已经详细了解了提供的捕获文件,这里是我的分析。 总之, 我认为这是你的路由器 ,这似乎是某种技术色彩的设备的问题。
具体来看,从客户端到服务器的stream量绝大多数会话开始合理的确定,但然后遇到丢包导致从客户端重传和超时。 例如,检查数据包编号161 – 207.在数据包161处,客户端向服务器发送一个数据包,但没有得到任何回应,导致客户端在连接断开之前重新传输大约15秒。
大多数的TCP数据streamcertificate了这种行为,所以我们可以得出结论,来自客户端的数据包没有到达服务器,或者来自服务器的响应没有到达客户端。
考虑延迟,服务器的SYN和SYN / ACK响应之间有一个明显的(和易变的)延迟,范围从168ms到770ms。
如果您为tcp.stream eq 1 || tcp.stream eq 2应用wireshark显示filter tcp.stream eq 1 || tcp.stream eq 2你可以看到双方的沟通。 具体来说,客户端>防火墙,然后防火墙>服务器(反之亦然)。 再次,一切都开始好了,然后围绕着数据包407事情变得有趣。
数据包#407标记了客户端向服务器发送一大块新数据的时间点。 路由器收到此消息并将其转发给服务器。 服务器发送一个确认数据包(数据包#410)以及另一个小数据包(#411)。 但是我们没有看到路由器将这些数据包传回给客户端 – 这是我发现这是路由器问题的最好证据。
比较一下,在跟踪数据包394到406中稍微进一步的成功交易之一,例如:
当事情失败的时候,所有事情都在第四阶段结束后停止 – 服务器发送的两个数据包似乎被丢弃在路由器上。