我试图了解接收器窗口如何影响高延迟连接的吞吐量。
我在相距很远的两台机器上有一对简单的客户端-服务器应用程序,两者之间的连接为 250 毫秒延迟 RTT。我在 Windows (XP, 7) 和 Linux (Ubuntu 10.x) 上运行了这个测试,结果相同,所以为了简单起见,我们假设以下情况:客户端接收数据:WinXP Pro 服务器发送数据:Win7 Pro 再次,延迟为 250 毫秒 RTT。
我在不更改客户端上的接收器缓冲区大小(默认为 8Kb)的情况下运行 TCP 测试,并且在线上看到(使用 Wireshark):
- 客户端向服务器发送 ACKS 并且 TCP 数据包包含 RWIN=65k
- 服务器发送数据并报告 RWIN=65k
查看跟踪,我看到了 3-4 个数据包的突发(有效负载为 1460 字节),紧随其后的是从客户端机器发送到服务器的 ACK,然后在大约 250 毫秒内什么都没有,然后是来自服务器的新数据包突发给客户。
因此,总而言之,服务器似乎在填满接收器窗口之前也没有发送新数据。
为了进行更多测试,这次我还运行了相同的测试,更改了客户端机器上的接收器缓冲区大小(在 Windows 上,更改接收器的缓冲区大小最终会影响机器通告的 RWIN)。我希望在阻塞 ACK 之前看到大量的数据包......并且至少有更高的吞吐量。
在这种情况下,我将 recv 缓冲区大小设置为 100,000,000。从客户端到服务器的数据包现在有一个 RWIN=99,999,744(嗯,这很好),但不幸的是,从服务器发送到客户端的数据模式仍然是相同的:短暂的突发,然后是长时间的等待。为了确认我在网络上看到的内容,我还测量了从服务器向客户端发送大量数据的时间。我没有看到使用大 RWIN 或使用默认值的任何变化。
谁能帮助我理解为什么更改 RWIN 并不会真正影响吞吐量?
几点注意事项: - 服务器使用 8Kb 块的 write() 尽可能快地发送数据 - 正如我之前所说,我在使用 Linux 时也看到了类似的效果。更改接收缓冲区大小会影响节点使用的 RWIN,但吞吐量保持不变。- 我在数百个数据包后分析跟踪,给 TCP 慢启动机制足够的时间来扩大 CWIN 大小。
正如建议的那样,我在这里添加了一个线迹的小快照
No. Time Source Destination Protocol Length Info
21 2.005080 CCC.CCC.CCC.CCC sss.sss.sss.sss TCP 60 57353 > 21500 [ACK] Seq=1 Ack=11681 Win=99999744 Len=0
22 2.005109 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=19305 Ack=1 Win=65536 Len=1460
23 2.005116 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=20765 Ack=1 Win=65536 Len=1460
24 2.005121 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=22225 Ack=1 Win=65536 Len=1460
25 2.005128 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 946 21500 > 57353 [PSH, ACK] Seq=23685 Ack=1 Win=65536 Len=892
26 2.005154 CCC.CCC.CCC.CCC sss.sss.sss.sss TCP 60 57353 > 21500 [ACK] Seq=1 Ack=14601 Win=99999744 Len=0
27 2.007106 CCC.CCC.CCC.CCC sss.sss.sss.sss TCP 60 57353 > 21500 [ACK] Seq=1 Ack=16385 Win=99999744 Len=0
28 2.007398 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=24577 Ack=1 Win=65536 Len=1460
29 2.007401 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=26037 Ack=1 Win=65536 Len=1460
30 2.007403 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=27497 Ack=1 Win=65536 Len=1460
31 2.007404 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=28957 Ack=1 Win=65536 Len=1460
32 2.007406 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=30417 Ack=1 Win=65536 Len=1460
33 2.007408 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 946 21500 > 57353 [PSH, ACK] Seq=31877 Ack=1 Win=65536 Len=892
34 2.007883 CCC.CCC.CCC.CCC sss.sss.sss.sss TCP 60 57353 > 21500 [ACK] Seq=1 Ack=19305 Win=99999744 Len=0
35 2.257143 CCC.CCC.CCC.CCC sss.sss.sss.sss TCP 60 57353 > 21500 [ACK] Seq=1 Ack=22225 Win=99999744 Len=0
36 2.257160 CCC.CCC.CCC.CCC sss.sss.sss.sss TCP 60 57353 > 21500 [ACK] Seq=1 Ack=24577 Win=99999744 Len=0
37 2.257358 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=32769 Ack=1 Win=65536 Len=1460
38 2.257362 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=34229 Ack=1 Win=65536 Len=1460
39 2.257364 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=35689 Ack=1 Win=65536 Len=1460
40 2.257365 sss.sss.sss.sss CCC.CCC.CCC.CCC TCP 1514 21500 > 57353 [ACK] Seq=37149 Ack=1 Win=65536 Len=1460
如您所见,服务器在数据包 #33 处停止发送数据。
客户端在旧数据包的数据包 #34 处发送 ACK(seq=19305,在数据包 #20 上发送,此处未显示)。使用 100Mb 的 RWIN,我希望服务器不会阻塞一段时间。
在 20-30 个数据包之后,服务器端的拥塞窗口应该足够大,可以发送比我看到的更多的数据包……我假设拥塞窗口最终会增长到 RWIN……但是,即使在一百数据包的模式是相同的:数据数据然后阻塞 250 毫秒......