TCPはどのように順序どおりの配信を実装するのか疑問に思いました。
これがイベントのリストだとしましょう
- packet1を送信し、ackを受信しました。
- packet2が送信され、ackが受信されませんでした。
- packet3が送信されました。
- packet4が送信されました。
- ack4を受信しました。
- ack3を受信しました。
- ack2を受信しました。
正確に順番に何が起こるか説明してもらえますか?
簡単に言うと、各パケットにはオフセット情報(シーケンス番号を装ったもの)が含まれており、そのペイロードがストリームのどこにあるかを指定します。
パケット1が受信され、パケット2が受信されず、パケット3と4が受信されたとします。この時点で、受信TCPスタックは、パケット3と4の内容をバッファーにコピーする場所を認識しており、以前のデータをまだ受信していないことを認識しているため、パケット1のデータを読み取り可能にしますが、作成しません。パケット2が受信されるまで利用可能なパケット3または4のデータ。
TCPスタックの送信は、通常、次のパケットを送信する前に単一のパケットの確認応答を待機しませんが、特定のパケットの確認応答を受信しない場合(ACKは効率のために単一のパケットにバンドルできます)。 ACKを受信するまで再送信してください。
イベントの正確な順序は、ネットワークの状態、TCPスタックの実装、選択したTCPポリシー、ソケットオプション、およびその他の要因によって異なります。
TCPパケットにはシーケンス番号(開始からのバイトオフセット、メモリから)があり、ACKメッセージは特定のオフセットが受信されたことを確認します。
したがって、次のような状況になる可能性があります。
data 1 (10 bytes) ->
<- ack (10, data1)
data 2 (15 bytes) ->
data 3 (10 bytes) ->
data 4 ( 8 bytes) ->
<- ack (25, data1/2/3)
<- ack (33, data1/2/3/4)
つまり、送信者は、バッファがいっぱいになるまで確認応答に関係なく送信を続けることができます(再送信する必要がある場合に備えて、確認応答されていないパケットを保持する必要があります)。
送信と確認応答の間のこの「切断」により、データフローを大幅に高速化できます。
受信側では、パケットが順不同で到着する可能性があり、何かがより高いレベルに順番に配信されるまで、パケットは保持されます。
たとえば、data 3
以前に到着した場合data 2
、受信側は到着するまでそれを保持data 2
し、その後、両方が上向きに送信されて配信されます。