レシーバーウィンドウが高遅延接続のスループットにどのように影響するかを理解しようとしています。
私は2台のマシン上に、250ミリ秒の遅延RTTの2つの間の接続を備えた、単純なクライアントサーバーペアのアプリを持っています。このテストをWindows(XP、7)とLinux(Ubuntu 10.x)の両方で実行したところ、同じ結果が得られたので、簡単にするために、次の場合を想定します。クライアントがデータを受信する:WinXP Proサーバーがデータを送信する:Win7 Pro遅延は250mSecRTTです。
クライアントのレシーバーバッファサイズ(デフォルトは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で送信、ここには示されていません)。RWINが100Mbの場合、サーバーがしばらくブロックしないことを期待します。
20〜30パケット後、サーバー側の輻輳ウィンドウは、私が見ているよりも多くのパケットを送信するのに十分な大きさになるはずです...輻輳ウィンドウは最終的にRWINまで大きくなると思います...パケットのパターンは同じです。データデータは250mSecの間ブロックされます。