套接字TCP服务器瓦特/ RTT和重传

我有一个在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,但是还没有成功。

我已经详细了解了提供的捕获文件,这里是我的分析。 总之, 我认为这是你的路由器 ,这似乎是某种技术色彩的设备的问题。

客户端捕获

  • 您的客户正尝试连接各种网站时遇到重大问题。 HTTPS网站(www.bing.com,wdcp.microsoft.com等)在Client Hello阶段后得不到响应,导致您的设备发生重传和最终超时。 对Akamai托pipe的网站(104.90.152.18)的另一组HTTP请求导致408请求超时。
  • 具体来看,从客户端到服务器的stream量绝大多数会话开始合理的确定,但然后遇到丢包导致从客户端重传和超时。 例如,检查数据包编号161 – 207.在数据包161处,客户端向服务器发送一个数据包,但没有得到任何回应,导致客户端在连接断开之前重新传输大约15秒。

    大多数的TCP数据streamcertificate了这种行为,所以我们可以得出结论,来自客户端的数据包没有到达服务器,或者来自服务器的响应没有到达客户端。

  • 考虑延迟,服务器的SYN和SYN / ACK响应之间有一个明显的(和易变的)延迟,范围从168ms到770ms。

服务器端捕获

  • 不幸的是,服务器端捕获不捕获客户端捕获相同的事件。 我也不确定在networking中究竟是在哪里捕获的,因为它包括客户端和服务器的stream量。 ICMPredirect也被发送,指示次优路由。 我不认为这是造成这个问题。
  • 如果您为tcp.stream eq 1 || tcp.stream eq 2应用wireshark显示filter tcp.stream eq 1 || tcp.stream eq 2你可以看到双方的沟通。 具体来说,客户端>防火墙,然后防火墙>服务器(反之亦然)。 再次,一切都开始好了,然后围绕着数据包407事情变得有趣。

    数据包#407标记了客户端向服务器发送一大块新数据的时间点。 路由器收到此消息并将其转发给服务器。 服务器发送一个确认数据包(数据包#410)以及另一个小数据包(#411)。 但是我们没有看到路由器将这些数据包传回给客户端 – 这是我发现这是路由器问题的最好证据。

比较一下,在跟踪数据包394到406中稍微进一步的成功交易之一,例如:

  1. (#394)客户端发送一个数据包给服务器的公共IP地址
  2. (#396)路由器收到此消息并将其转发给服务器的本地IP地址
  3. (#397)服务器将确认发送回客户端的NAT'd IP
  4. (#398)服务器发送一个小数据包回到客户端的NAT'd IP
  5. (#401)路由器将确认回送到客户端的本地IP
  6. (#402)路由器将小数据包发送回客户端的本地IP
  7. (#403)客户端向服务器的公共IP发回一个确认,确认它收到了服务器发送的数据
  8. (#406)路由器将确认转发到服务器的本地IP。

当事情失败的时候,所有事情都在第四阶段结束后停止 – 服务器发送的两个数据包似乎被丢弃在路由器上。

最后的想法

  • 大部分的TCP连接,不只是你的Python应用程序,似乎正在遭受性能问题的困扰,正如客户端捕获中的许多连接问题所表明的那样。
  • 在您的服务器端捕获有合理的证据表明,当数据包必须通过路由器转发时,数据包将被黑掉。
  • 您的testing得出的结论是,在本地testing此应用程序时没有问题,此时stream量不需要穿过路由器进行端口转发。
  • 不幸的是,我对Technicolor路由器根本不熟悉,唯一可以build议的是检查是否在路由器上启用了防火墙或服务质量规则,这可能会影响性能。 也许如果你可以使用另一个路由器进行testing,或者在另一个networking上托pipe你的应用程序,看看问题是否存在。