コンピュータネットワークのTCP/IP
プロトコルスタックには、トランスポート層にある2つの最も一般的なプロトコルがTCP
ありUDP
ます。と言えば、TCP
始めるための2つの知識ポイントもテストポイントであり、疑わしいポイントとなる詳細でさえ、スリーウェイハンドシェイクとフォータイムウェーブです。
このステートマシンからのオープニング、tcpステートマシンの写真から、今回説明する2つのトピックを見ることができます。
3つのハンドシェイク
スリーウェイハンドシェイクの一般的な内容は、以下に示すように漫画として描くこともできます。
嘲笑は嘲笑に属しますが、真実はまだ同じです。TCPの目的は、信頼性の高いバイトストリームサービスを提供することであることがわかっています。データを宛先に正確に配信するために、TCPプロトコルは3方向ハンドシェイク戦略を採用して伝送チャネルを確立します。プロセスは次のとおりです。
- 最初は、両端のTCPプロセスが
CLOSE(关闭)
状態になっています。 - 送信者Aは、
SYN( synchronize)
フラグ付きのデータパケットを受信者Bにアクティブに送信します。このとき、Aはアクティブ(active open)
にconnect
サーバーにアクセスして送信しSYN
ます。シリアル番号がJであるとすると、受信者はパッシブ(passive open)
です。注意が必要なのは、クライアントとサーバーから送信されるシリアル番号がランダムであるということです。 - SYNを受信した後、受信者Bは、接続の確立に同意すると、送信側Aに別の戻りSYNとACK(確認応答)を送信
J+1
します。ACKシーケンス番号はSYNJ
応答として表され、SYN新しい送信K
シーケンス番号はいK
、データパケットは確認メッセージを配信します。これは、私がそれを受信したことを意味します。このシリアル番号もランダムです - 送信者Aは、
ACK
フラグ付きのデータパケットを送り返します。これは、私がそれを知っていることを意味し、ハンドシェイクは終了します。新しいSYNK
とACKを受信した後J+1
、送信者もACKで応答して、受信K+1
したことを示し、接続チャネルが確立されます。 - その後、双方がデータの送信を開始できます
自然
まず、TCPメッセージのヘッダーの形式を見てみましょう。
ここでのTCPメッセージには実際には多くのコンテンツが含まれていますが、制御ビットは3ウェイハンドシェイクと4つのウェーブに関連しているため、今回は制御ビットのみに焦点を当てます。
- URG:URG = 1の場合、緊急ポインタフィールドが有効であることを示し、このセグメントに緊急データがあることをシステムに通知し、最初に送信されます。
- ACK:ACK = 1の場合、確認番号フィールドは有効であり、ACK = 0の場合、確認番号フィールドは無効です。
- PSH:PSH = 1のTCPセグメントを受信した後、バッファ全体がいっぱいになるのを待ってから上向きに配信するのではなく、できるだけ早くアプリケーションプロセスに配信されます。
- RST:RSH = 1の場合、TCP接続にエラーがあることを示します。接続を解放してから再確立する必要があります。
- SYN:SYN = 1は、これが接続要求または接続受け入れメッセージであることを意味します。
- FIN:FIN = 1は、このメッセージセグメントの送信者のデータが送信され、トランスポート接続を解放する必要があることを意味します。
なお、スリーウェイハンドシェイク後にデータを送信する場合、ハンドシェイク後にクライアントから最初のパケットが送信された場合、最初のパケットのseqとackは3番目のハンドシェイクと同じであり、seq ackは、最後に受信したパケットのseq、ack、およびlen(データ長)に従って取得されます。具体的には、seq = ack、ack = seq + lenです。
シリアル番号の役割
シーケンス番号の機能は、TCP受信機が繰り返しセグメントを破棄し、無秩序に到着したセグメントを記録できるようにすることです。TCPはIPを使用してメッセージセグメントを送信し、IPは重複を排除する機能を提供したり、正しい順序を保証したりしないためです。一方、TCPはバイトストリームプロトコルであり、データを無秩序な順序で上位プログラムに送信することはありません。したがって、TCPレシーバーは、大きなシーケンス番号のデータを保持し、欠落している小さなシーケンス番号セグメントが埋められるまでアプリケーションプログラムにデータを渡さないように強制されます。
我々はしているRFC793 TCPのプロトコルRFCあり、そしてあなたはそれが3ウェイハンドシェイクが必要な-TCPは信頼性の高い再送信または受信のための配列のシーケンス番号を必要とし、中に配列を区別できないことを回避している理由について語っていることがわかります接続の再利用遅延リンクまたは古いリンクのシーケンスであるため、両方の当事者のISN(初期シーケンスシーケンス番号)を決定することに同意するには、スリーウェイハンドシェイクが必要です。
設計の基本的な概念は、TCP接続を介して送信されるデータのすべてのオクテットにシーケンス番号があるということです。すべてのオクテットがシーケンスされているため、それぞれを確認できます。採用された確認応答メカニズムは累積的であるため、シーケンス番号Xの確認応答は、Xまでのすべてのオクテットが受信されたことを示します。
TCP設計の基本設定では、TCP接続を介して送信されるすべてのパケットに1つsequence number
があり、すべてのパケットにシーケンス番号があるため、これらのパケットの受信を確認できます。確認メカニズムは累積的であるため、sequence number
Xの確認は、Xシーケンス番号(Xを除く)より前のすべてのパケットが受信されたことを確認することを意味します。
プロトコルは、何度も何度も使用される特定の接続に制限を課しません。これから生じる問題は、「TCPは、接続の以前のインカネーションから重複するセグメントをどのように識別するのですか?」です。この問題は、接続がすばやく連続して開閉されている場合、または接続がメモリの喪失によって切断されてから再確立された場合に明らかになります。
TCPプロトコルは、再利用する特定の接続(両端のソケットは同じ)を制限しません。したがって、質問があります。接続が突然切断されて再接続された後、TCPは古いリンクから再送信されたパケットをどのように認識しますか?-これには、固有のISN(初期シリアル番号)メカニズムが必要です。
新しい接続が作成されると、新しい32ビットISNを選択する初期シーケンス番号(ISN)ジェネレーターが使用されます。ジェネレータは、(架空の)32ビットクロックにバインドされており、その下位ビットは約4マイクロ秒ごとにインクリメントされます。したがって、ISNは約4.55時間ごとに循環します。セグメントがネットワークにとどまるのは最大セグメント寿命(MSL)以下であり、MSLは4.55時間未満であると想定しているため、ISNは一意であると合理的に想定できます。
新しい接続が確立されると、初期シーケンス番号(初期シーケンス番号ISN)ジェネレーターが新しい32ビットISNを生成します。
ISNは次のように計算されます。
ISN = M + F(localhost, localport, remotehost, remoteport)
ここで、Mはタイマーであり、4 µsごとに1ずつ増加します。Fは、送信元IP、宛先IP、送信元ポート、および宛先ポートに基づいてランダムな値を生成するハッシュアルゴリズムです。
このジェネレーターは、ほぼ4µs
1回成長する32ビットの長いクロックを使用するためISN
、4.55時間ごとに循環します。
また、ネットワーク内のセグメントは最大セグメント寿命より長くなくMSL Maximum Segment Lifetime
、デフォルトの使用は2分長く、MSLは4.55時間より短いため、ISNは一意であると考えることができます。
スリーウェイハンドシェイクの役割
TCP接続は、2つのIPアドレスと2つのポート番号である4タプルで構成されます。TCP接続は通常、開始、データ送信、および終了(クローズ)の3つの段階に分けられます。クライアントとサーバーは通信する前に接続する必要があります。「3ウェイハンドシェイク」の機能は、両方の当事者が自分自身と相手の送受信機能が正常であることを知ることができることです。
スリーウェイハンドシェイクの重要な機能の1つは、クライアントとサーバーがISN(初期シーケンス番号)を交換することです。これにより、相手は次にデータを受信するときにシーケンス番号に従ってデータを組み立てる方法を知ることができます。
3回握手する必要がありますか?
スリーウェイハンドシェイク中の実際の効果は、サーバーが認識していることをクライアントが認識していることをサーバーに通知することです。これは確かにマトリョーシカの意味であり、疑わしいかもしれませんが、クライアントが知っていることをサーバーに知らせるだけで十分ですか?または、サーバーが知っていることをクライアントが知っていることをサーバーが知っていることをクライアントに知らせる必要はありませんか?なぜ不要なのですか?著者は、Xie Xiren先生の本で自分の見解を学ぶことができます。彼の見解は、無効な接続要求メッセージが突然反対側に送信されてエラーが発生するのを防ぐことです。
Xie先生はさらに、いわゆる「接続失敗要求セグメント」がこの方法で生成されたと説明しました。
- 通常の状況を考えてみましょう。Aは接続要求を送信しますが、接続要求メッセージが失われたため、確認を受信していません。そのため、Aは接続要求を再送信します。その後、確認が受信され、接続が確立されました。データ転送が完了すると、接続が解放されます。Aは合計2つの接続要求セグメントを送信しました。最初のセグメントは失われ、2番目のセグメントはBに到達し、「失敗した接続要求セグメント」はありません。
- ここで、異常な状況が発生したとします。つまり、Aによって送信された最初の接続要求メッセージセグメントは失われませんが、一部のネットワークノードに長時間留まるため、接続が解放されてから一定時間まで遅延します。 。。もともと、これは長い間期限切れになっているセグメントです。しかし、Bはこの無効な接続要求セグメントを受信した後、Aが新しい接続要求を送信すると間違えます。そのため、接続を確立することに同意して、確認応答セグメントをAに送信します。メッセージハンドシェイクが使用されていないと仮定すると、Bが確認応答を送信している限り、新しい接続が確立されます。
- Aは接続を確立するための要求を送信していないため、Bの確認を無視し、Bにデータを送信しません。しかし、Bは新しいトランスポート接続が確立されたと考え、Aがデータを送信するのを待っていました。このようにして、Bのリソースの多くが無駄になりました。
以上がアカデミックスクールの理解です。主に例外処理の観点から分析します。双方向ハンドシェイクの場合、輻輳による再接続が発生すると、ピアサービスの例外が発生し、例外処理メカニズムを設計する必要があります。
後で、GoogleグループのTopLanguageで、TCPの「スリーウェイハンドシェイク」について議論している投稿を見て、それが非常に興味深いことに気づきました。ポスターは、「なぜTCP接続がスリーウェイハンドシェイクによって確立されるのか」という質問を提起しました。多くの回答の中で、ある回答は次のように書いています。「この問題の本質は、チャネルの信頼性が低いことですが、二重通信はこの問題を解決するには、メッセージにどのような情報を含めても、3回の通信が理論上の最小値であるため、3ウェイハンドシェイクはTCP自体の要件ではなく、要件を満たすためのものです。 「信頼性の低いチャネルでの情報の信頼性の高い送信」の例。需要に起因します。ここでの重要な要件に注意してください。チャネルの信頼性が低く、データ送信の信頼性が必要です。3回後、握手したり、データを送信したりします。したがって、チャネルが信頼できる場合、つまりメッセージが送信されるたびに相手がそれを受信できる場合、または相手がメッセージを受信するかどうかを気にしない場合は、そうすれば、UDPのように直接メッセージを送信できます。」
実際、これは「スリーウェイハンドシェイク」の目的のための別の詮索好きな角度と見なすことができます。フルスクリーンのエンジニアリングの考え方は、結局のところ、これは信頼性の低いチャネル送信への妥協であり、信頼性の高い情報の送信を完了します。結局のところ、スリーウェイハンドシェイクは2つの重要な機能を完了します。両方の当事者がデータを送信する準備をし(双方がお互いの準備ができていることを知っている)、ハンドシェイクプロセスで使用される最初のシリアル番号について交渉できるようにする必要があります。 。送信して確認します。
たとえば、3ウェイハンドシェイクを2ハンドシェイクのみに変更すると、デッドロックが発生する可能性があります。コンピュータSとCの間の通信が、この時点でCがSに接続要求パケットを送信し、Sがこのパケットを受信し、確認応答パケットを送信するとします。2つのハンドシェイク合意によれば、Sは接続が正常に確立されたと見なし、データパケットの送信を開始できます。ただし、送信中にSの応答パケットが失われると、CはSの準備ができているかどうか、またはSが確立したシーケンス番号を認識できず、Sが独自の接続要求パケットを受信したかどうかさえ疑うことになります。この場合、Cは接続が正常に確立されていないと見なし、Sから送信されたデータパケットを無視し、接続確認応答パケットのみを待ちます。そして、送信されたパケットがタイムアウトした後、Sは同じパケットを繰り返し送信します。これにより、デッドロックが発生します。示されているコミックイラスト
前の説明では、送信者と受信者の両方が相互に通信するための独自のISN(次の例ではXとY)を持っていることがわかっています。具体的な説明は次のとおりです。
1. A --> B SYN my sequence number is X
2. A <-- B ACK your sequence number is X
3. A <-- B SYN my sequence number is Y
4. A --> B ACK your sequence number is Y
2と3の両方がBからAに送信されるため、これらを組み合わせて3ウェイ(または3メッセージ)ハンドシェイクを形成できます。この時点で、3ウェイハンドシェイクが必要であると結論付けることができます。
シーケンス番号はネットワーク内のグローバルクロックに関連付けられておらず、TCPにはISNを選択するためのさまざまなメカニズムがある可能性があるため、3ウェイハンドシェイクが必要です。最初のSYNの受信者は、接続で使用された最後のシーケンス番号を記憶していない限り(常に可能とは限りません)、セグメントが古い遅延セグメントであったかどうかを知る方法がないため、送信者に確認を求める必要があります。このSYN。3ウェイハンドシェイクとクロック駆動方式の利点については、[3]で説明されています。
シーケンス番号(シーケンス番号)はネットワーク全体のグローバルクロックにバインドされていないため(すべて単一のクロックを使用するため、パケットが遅延するかどうかを判断できます)、TCPはISN(初期シーケンス番号)を選択するメカニズムが異なる場合があります。
受信者が最初のSYNを受信すると、この接続で受信した最後のシーケンス番号を記憶する方法がない限り、SYNが長時間遅延しているかどうかを知る方法はありません(ただし、これが常に実行可能であるとは限りません)。
この文の意味は次のとおりです。seqが来ましたが、現在記憶されているseqとは異なります。遅延しているか遅延しているかを知るにはどうすればよいですか。したがって、受信者は送信者にSYNを確認する必要があります。
SYNのSEQが確認されていないと仮定すると、次のようになります。
1) A --> B SYN my sequence number is X
2) A <-- B ACK your sequence number is X SYN my sequence number is Y
BだけがAのSEQの受信を確認し、AはBの受信を確認できませんでした。つまり、AからBに送信されたパケットのみが信頼できますが、BからAに送信されたパケットは信頼できないため、これは信頼できる接続ではありません。この場合、AだけがBに送信する必要があり、Bが応答する必要がない場合は、スリーウェイハンドシェイクを省略できます。
Four-Way-Wavehand
3つのハンドシェイクについて話した後、それは他の4つの波についても同じですか?妥協するために、異常な状況を排除するために?ステップバイステップで演繹的に推論しましょう。
- 初めてWave:クライアントはFINを送信して、クライアントからサーバーへのデータ転送を閉じ、クライアントはFIN_WAIT_1状態になります。
- 2番目の波:FINを受信した後、サーバーはクライアントにACKを送信し、シリアル番号が受信したシリアル番号+1であることを確認し(SYNと同じ、1つのFINがシリアル番号を占有)、サーバーはCLOSE_WAIT状態になります。 。このとき、TCPはハーフクローズ状態であり、サーバーはクライアントにデータを送信できますが、サーバーはデータを送信できません。
- 3番目の波:サーバーはFINを送信してサーバーからクライアントへのデータ転送を閉じ、サーバーはLAST_ACK状態になります。
- 4番目の波:クライアントがFINを受信した後、クライアントはTIME_WAIT状態に入り、2 MSL(最大メッセージ存続時間)を待ってから接続を解放し、サーバーにACKを送信して、シリアル番号が受信されたことを確認します。シリアル番号+1で、サーバーはCLOSED状態を確認した後、接続を解放し、4つのウェーブを完了します。
人気のことわざ:
- クライアント:私はすべてについて話し終えました
- サーバー:私はそれらすべてを聞いたが、私を待って、私は終わっていない
- サーバー:わかりました、完了しました
- クライアント:わかりました、それで私たちのコミュニケーションは終わりました:)
意義
パッシブパーティがアクティブパーティからFINメッセージ通知を受信した場合、それはアクティブパーティにパッシブパーティに送信するデータがないことを意味するだけです。ただし、必ずしもパッシブパーティのすべてのデータがアクティブパーティに完全に送信されているとは限らないため、パッシブパーティはすぐにSOCKETを閉じません。アクティブパーティにデータを送信してから、アクティブパーティにFINメッセージを送信する必要がある場合があります。パーティ、アクティブなパーティに同意するように指示接続は閉じられているため、ここでのACKメッセージとFINメッセージはほとんどの場合別々に送信されます。
理由
2つの状態がClose-wait
あり、Time-wait
手の波の間にあることに注意してください。これが、実際には4方向ハンドシェイクを設計する必要がある理由です。
クローズウェイト
クライアントがFIN
接続解放メッセージを送信した後、サーバーはメッセージを受信してCLOSE-WAIT
状態に入ります。この状態は、サーバーがまだ送信されていないデータを送信するためのものです。送信が完了すると、サーバーはFIN
接続解放メッセージを送信します。
タイムウェイト
クライアントFIN
は、サーバーからのメッセージを受信した後、この状態になります。このとき、クライアントは直接CLOSED
状態に入るわけではなく、タイマーで設定された時間待つ必要があります2MSL
。
なぜAはTIME-WAIT状態で2MSLを待たなければならないのですか?
これには2つの理由があります。
- Aによって送信された最後のACKセグメントがBに到達できるようにするため。Aから送信されたACKメッセージセグメントが失われる可能性があります。BがAから送信された確認メッセージを受信しない場合、Aは接続解放要求メッセージを再送信します。Aはこの状況に対処するために一定時間待機します。
- 「失敗した接続要求セグメント」がこのリンクに表示されないようにします。Aが最後のACKセグメントを送信し、2MSLが経過すると、この接続の時間内に生成されたすべてのセグメントがネットワークから消えることがあります。このようにして、古い接続要求セグメントは次の新しい接続に表示されません。
4回握手する必要がありますか?
これは、サーバーのLISTEN状態のSOCKETがSYNメッセージの接続要求を受信すると、ACKとSYN(ACKは応答、SYNは同期)を1つのメッセージで送信できるためです。しかし、相手のFINメッセージ通知を受信したときに、接続が積極的にそれは相手があなたに送信するデータがないことを唯一の手段は、閉じられたときに、ではなく、それはので、すべてのデータは、相手に送信されてきたかもしれません必ずしもすぐにSOCKETを閉じる必要はありません。つまり、データを相手に送信してから、FINメッセージを相手に送信して、今すぐ接続を閉じることができることに同意したことを示す必要がある場合があります。そのため、ACKメッセージが表示されます。ここでのFINメッセージはほとんど別々に送信されます
経験
尾根と山のように水平に見ると、この問題をさまざまな角度と視点から見ることは、確かに多くの利益をもたらしました。