4

レシーバーウィンドウが高遅延接続のスループットにどのように影響するかを理解しようとしています。

私は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の間ブロックされます。

4

4 に答える 4

8

あなたが提供したサンプルから2つのことを推測できます:

  1. サーバーには約15kの送信バッファーがあります。
  2. 提供するダンプはサーバー側で実行されました。

TCP接続のウィンドウを特定のサイズに拡大するには、送信側の送信バッファーと受信側の受信バッファーの両方が十分に大きい必要があります。

使用される実際のウィンドウは、受信者によって提供/要求された受信ウィンドウと送信者のOSで設定された送信バッファサイズの最小値です。

簡単に言うと、サーバーで送信バッファーのサイズを構成する必要があります。

問題を解決するために、サンプルパケットをパケットごとに分析してみましょう。

サーバーは別のデータを送信します。

 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

に注意してPSHください。これは、データの完全なチャンクが送信されたことをその間のホップに示すフラグです。もう一方の端に送信してください。(この場合、「完全な」チャンクは8kbです)

サーバーがまだ送信している間、2つのACKSを取得します。

 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
 

特に数字に注意してください:Ack=14601Ack=16385。これらの番号は、受信者が確認しているパケットのシーケンス番号です。

Ack = 14601は、「seqno14601までのすべてを受け取った」という意味です。

また、これらは古いデータであり、提供したサンプルには含まれていないことにも注意してください。

したがって、サーバーはこれらのACKを処理し、データの送信を続行します。

 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

ここにデータの完全なブロックがあります:1460 * 5 + 892==8192。

次に、最後のパケットを送信してから0.443ミリ秒後に、もう1つのACKを取得します。

 34 2.007883    CCC.CCC.CCC.CCC       sss.sss.sss.sss       TCP      60     57353 > 21500 [ACK] Seq=1 Ack=19305 Win=99999744 Len=0

そして、サーバーがこれらを受信する前に、ほぼ正確に250msの遅延があり、その間、サーバーは何も送信しません。

 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

ここで注目すべき2つの非常に興味深いことがあります。
まず、ACKを待たずにサーバーから送信されたバイト数。その遅延の前にサーバーが受信した最後のACKシーケンス番号はAck=19305、であり、その時点でサーバーによって送信された最後のパケットのシーケンス番号はですSeq=30417

そのため、その一時停止中に、サーバーが送信した11112バイトが、クライアントによってまだACKされていません。

第二に、それはサーバーが大量のデータを送信した直後にサーバーが受信した1つのACKであり、それ以上の送信をトリガーしませんでした。そのACKが十分ではなかったかのようです。

その前に受信したACKはAck=16385、その時点で未確認のサーバーによって送信された30417-16385=14032バイトを与えていました。seq no 24577のACKを受信し、そのカウントを30417-24577 = 5840に減らした後でのみ、サーバーは送信を再開しました。

したがって、8kのバッファーサイズが16kの有効ウィンドウサイズと比較して大きいという事実は、サーバーがすべてのスペースができるまで8kブロックを送信しないため、スループットが実際にいくらか低下することを意味します。

最後に、疑問に思っている人のために、ウィンドウスケーリングと呼ばれるTCPオプションがあります。これにより、接続の一方の端で、ウィンドウサイズが実際にはTCPヘッダーの数値の倍数であることを宣言できます。RFC1323を参照してください。このオプションはSYNパケットで渡されるため、接続中には表示されません。ウィンドウサイズのTCPヘッダーが使用されているウィンドウよりも小さいため、ウィンドウスケーリングが有効であるというヒントのみがあります。

于 2012-04-24T02:26:26.947 に答える
1

ソケットが接続されると、受信バッファサイズを64k以上に設定することはできません。あなたは最初にそれをしなければなりません。リスニングソケットで受信バッファサイズを設定することを意味するサーバーの場合:受け入れられたソケットは、受け入れられたソケットからそれを継承します。これを行わないと、TCPウィンドウスケーリングオプションをネゴシエートできないため、ピアは64kを超えるサイズについて相互に通知することができません。

于 2012-04-24T01:37:32.213 に答える
0

送信側マシンが受信側からackを受信した時点で、送信側マシンは送信するためにどのくらいのデータをキューに入れていますか?TCPはストリームベースのプロトコルであり、データストリーム内にパケットブレークがないため、TCP送信者は、部分的なパケットを送信するタイミングと、さらにデータが到着するのを待機するタイミングを知る方法がありません。通常、TCP実装がパケットのACKを受信した場合、送信バッファが空になるまで送信する価値があると判断しますが、データが送信のためにキューに入れられた後、別のACKを受信するまで待ってから別のACKを送信する場合がありますバッチ。

于 2012-04-23T23:24:30.340 に答える
0

レシーバーウィンドウのサイズは、スループットに直接影響します。スループット<=RWIN/RTT。

いくつかのことがスループットを低下させる可能性もあります。ヘッダーのECNビットが1に設定されていますか?どちらかの側でパケット損失があるかどうか知っていますか?サーバーがタイムアウトしているようです。クライアント側で着信パケットと発信ACKのシーケンス番号を印刷し、サーバー側で同様の情報を印刷できますか。受信者のシーケンス番号が5で、6,7,8,9を受信した場合、受信者は6,7,8,9をACKします。ただし、6が失われた場合、パケット7、8、9を受信したときに5をACKします。シーケンス番号は多くの情報を明らかにすることができます。

250msの一時停止はタイムアウトのようです。

スロースタート

アルゴリズムは、最初は1または2セグメントの輻輳ウィンドウサイズ(cwnd)で指数関数的成長フェーズで開始され、受信したACKごとに1セグメントサイズ(SS)ずつ増加します。受信者は通常、2つのセグメントごとにACKを送信するため、この動作により、ネットワークのラウンドトリップごとにウィンドウサイズが実質的に2倍になります。この動作は、輻輳ウィンドウサイズ(cwnd)が受信者のアドバタイズされたウィンドウのサイズに達するまで、または損失が発生するまで続きます。

何が起こっているのかというと
、サーバーは1パケットを送信し、1 ackを取得
しますサーバーは2パケットを送信し、2 acks(2,3)
を取得しますサーバーは4パケットを送信し、4 acks(4,5,6,7)
を取得しますサーバーは8パケットを送信し、4を取得しますacks(クライアントがパケットを取得する前にドロップされたパケット)(8,9,10,11)(タイムアウト12)
サーバーは4つのパケットを送信し、4つのacks(12,13,14,15)
を取得しますサーバーは5つのパケットを送信し、4つのacks(16、 17,18,19)(タイムアウト20)
サーバーは3つのパケットを送信し、3つのackを取得します(20,21,22)
サーバーは4つのパケットを送信し、4つのackを取得します(23,24,25,26)
サーバーは5つのパケットを送信し、4つのackを取得します(27,28,29,30)(タイムアウト31)
サーバーは3,4,5ループを続行します

于 2012-04-23T23:59:26.797 に答える