目次
序文
前回の記事では、UDP の実装方法について紹介しましたが、今回は TCP について紹介します。TCP プロトコルは信頼できると言われていますが、今回はなぜ TCP プロトコルが信頼できるのかを見ていきます。信頼性の高い実装に使用されます。
1.TCPプロトコル
TCP は「Transmission Control Protocol」の略で、その名のとおり、データ伝送を詳細に制御する必要があります。
データがトランスポート層にコピーされるとき、データが下方向に送信され続けるとき、オペレーティング システムは独自の送信戦略を持っているため、TCP プロトコルは送信制御プロトコルと呼ばれます。TCP プロトコルには送信バッファと受信バッファの両方があります。 、つまり TCP は全二重です
写真が示すように:
2.TCPプロトコルセグメントフォーマット
a. TCP プロトコルヘッダーの長さは標準で 20 バイトですので、読み出す場合は最初に 20 バイトを読み取ってください。
b. 構造化データに変換し、標準ヘッダーの 4 桁のヘッダー長を抽出し、TCP メッセージの全長 =
4 桁のヘッダー長 * 4 バイト [0,60]、ヘッダーが 20 バイトの場合、4 桁のヘッダー長は 5 x * 4 バイト = 20 x = 5 [0101] に入力する必要があります。
c. 後続のヘッダーの残りのサイズを取得します: x*4 - 20 = 0; x * 4 - 20 = n;
d. ヘッダーが処理される限り、残りはペイロードです
3. 開梱・分別方法
開梱: 上記のように開梱します。
分散化: ヘッダー内の宛先ポート番号に基づいて、アプリケーション層のプロセスを見つけることができ、データを上向きに配信できます。
4. ネットワークプロトコルスタックとファイルの関係
写真が示すように:
5. TCPヘッダーの理解方法
ヘッダーは言語レベルの構造化データの一種です。
struct tcp_ hdr
{
uint32_t src_port:16;
uint32_t dst_port:16;
uint32_t seq;
uint32_t ack_seq;
uint32_t header_length:4;
....
};
6. TCPの特徴
信頼性、高い伝送効率
a. 信頼性を理解する:
信頼性が低い理由: ネットワーク伝送における信頼性が低い根本的な理由は、伝送距離が長くなったことにあります 信頼性が低い
シナリオ: パケット損失、障害、検証エラー、重複... ...
b.tcp はどのように保証しますか信頼性:
信頼性の知覚的理解
A と B のコミュニケーション:
距離が長くなると、絶対的な信頼性はありませんが、相対的な信頼性はあります。
相対的な信頼性を確保するにはどうすればよいでしょうか?
メッセージが応答を受信する限り。メッセージの信頼性を保証できます。TCP
は信頼性を確保するために確認応答メカニズムを使用します。双方間の通信には最新のニュースがなければなりません。応答がない場合、最新のニュースは一般に信頼性を保証できません。
TCP の動作モードを理解します。
信頼性を確保するために、クライアントからサーバー、またはサーバーからクライアントへの応答が必要であり、両者が通信する際には、通常のデータセグメントに加えて、確認データセグメントが含まれる場合があります。
TCP の実際の動作モード:
TCP プロトコルのデータが送信されるとき、相手側に到達する順序は、送信された順序と必ずしも同じではありません。
上記の問題を解決するには、データセグメント自体を識別する方法が必要です. データセグメント自体は、シリアル番号と確認用シリアル番号によって識別されます.
シリアル番号と確認用シリアル番号の理解:
シリアル番号 = シリアル番号 + 1 で連続していることを確認します。
シーケンス番号が 2 セットある理由: TCP は全二重であるため、クライアントはサーバーにメッセージを送信し、サーバーはクライアントにメッセージを送信します。
実シーケンス番号: TCP プロトコルによって送信されるデータはバイト ストリーム指向であるため、データの各バイトには番号、つまりシーケンス番号が付けられます。
各 ACK には、対応する確認シーケンス番号が含まれています。これは、受信したデータと次回どこから送信を開始するかを送信者に伝えることを意味します。
7.TCPフィールド
7.1 16ビットウィンドウサイズ
TCP がデータを送信するとき、速くも遅くもできません。適切なデータが送信されることを確認するにはどうすればよいですか? 解決策
: 16 ビットのウィンドウ サイズは基本的にバッファです。一方の当事者が他方の当事者にデータを送信するとき、データのサイズを埋めます。ヘッダーのバッファーの残りスペース! データ送信中のフロー制御は 16 ビット ウィンドウを通じて実装されます。
7.2 フラグビット
サーバーはさまざまなメッセージを受信し、受信側はさまざまなメッセージに応じてさまざまなアクションを実行する必要があります。TCP メッセージにもタイプがあり、いくつかは通常のデータ セグメントであり、いくつかはさまざまなフラグ ビットに従って、ACK 確認データ セグメントです。行動。
TCP メッセージ タイプの分類: URG、ACK、PSH、RST、SYN、FIN
SYN:コネクション確立時、フラグを1に設定
FIN:コネクション切断時、フラグを1に設定
ACK:メッセージが確認応答型の場合、フラグを1に設定
PSH:受信時相手がいっぱいの場合、送信者は受信者にできるだけ早くデータを取り出し、この情報を通知し、フラグを 1 に設定するように促します。
URG:
受信機にとって、順序が乱れたデータは信頼性の低いパフォーマンスであるため、データが時間通りに到着するように受信データをソートする必要があります! ソート方法は? シリアル番号でソートした後: 受信機のバッファーの領域は次のとおりです
。このとき、キュー
にジャンプしたいデータが存在する可能性はありますか? キューにジャンプしたいデータがある場合、データ メッセージ内の URG が 1 に設定され、URG を持つデータ メッセージが設定されます
。 16 ビット緊急ポインターへの
16 ビット緊急ポインターを識別します: ペイロード内のオフセット
データには数バイトがあります: TCP プロトコルでは、データは 1 バイトのみです。
このとき、データはアプリケーション層を事前に読み取り、データキュージャンプを実現します。この種のデータは一般に帯域外データと呼ばれます
使用シナリオ: サーバーの状態の検出
アプリケーション層で帯域外データを識別するにはどうすればよいですか?发送方: send . ssize_t send(int sockfd, const void *buf, size_t len,int flags) ; flags: MSG_ OOB 接受方: recv ssize_t recv(int sockfd, void *buf, size_ t len,int flags) ; flags: MSG_ OOB
RST:
3 ウェイ ハンドシェイクにより接続が正常に確立されます。接続が成功した場合でも、通信プロセス中に一方的な問題が発生する可能性があります。一方の当事者にとっては接続がまだ存在します。問題のある当事者にとっては、接続は存在しませんが、問題が発生している当事者にとっては接続が存在しません
。問題のある方にとっては問題ありません。接続がまだ存在すると判断した場合は、相手にデータを送信します。このとき、問題のある方にデータが送信されると、問題のある方はそれを検出します。接続は切断されましたが、まだデータを送信しています。この時点で、RST フラグが設定されます。1 に設定すると、接続の回復が示されます。
8. タイムアウト再送信
データ送信中のパケット損失を理解する方法:
パケット損失には 2 つの可能性があります:
1. 送信時にデータが失われる
2. 受信者から送信者に送信された応答が失われる
上記 2 つの場合に合わせてカスタマイズされた TCP プロトコルの戦略は次のとおりです。時間をかけて再送信します
。2 番目のケースの場合、送信者は同じデータの 2 つのコピーを受信者に送信します。このとき、重複を排除する必要があります。重複を排除する方法は?シリアル番号を使用して重複を排除できます。存在
します 再送信の可能性は、送信者によって送信されたデータが送信後すぐに削除されないことを意味します。
タイムアウトの理解方法:
タイムアウトはネットワークの状況に基づいて決定され、変動する時間間隔です!
一般に、最も理想的な状況では、「確認応答がこの時間内に返される必要がある」ことを保証するための最小時間を見つけます。 Linux
(BSDUnix) (Windowsも同様)、タイムアウトは500ms単位で制御されており、再送信ごとのタイムアウト時間は500msの整数倍となります。1回再送信しても応答が得られない場合は、2*500ms待ってから再送信してください
。送信
それでも応答がない場合は、再送信を 4*500ms 待つなど指数関数的に増加し、一定
回数の再送信が蓄積されると、TCP はネットワークまたは対向ホストに異常があると判断し、強制終了します。接続。
9. 接続管理メカニズム
通常の状況では、TCP は接続を確立するために 3 回のハンドシェイクを必要とし、切断するには 4 回のウェーブを必要とします。
3 ウェイ ハンドシェイクを理解する方法:
3 ウェイ ハンドシェイクは、TCP プロトコルで接続を確立するためのカスタマイズされた戦略です。3 ウェイ ハンドシェイクは、接続が成功することを必ずしも保証しません。1 回のハンドシェイクと 2 回のハンドシェイクは機能しますか
? ?
答えは決してそうではなく、クライアントとサーバーが接続を確立するとき、その接続は OS によって管理される必要があるため、最初にその管理方法について説明し、次に整理します。
管理には時間とスペースのコストがかかり、1 回のハンドシェイクと 2 回のハンドシェイクで接続が成功すると、サーバーがクライアントから攻撃を受ける可能性があります。この攻撃は一般に SYN フラッドと呼ばれます。
3 ウェイ ハンドシェイクの特徴:
a. 最小コストを使用して、全二重通信チャネルがスムーズであることを検証する
b. 3 ウェイ ハンドシェイクは、単一マシンによるサーバーへの攻撃を効果的に防止できます
。接続?
Tcp は信頼性を確保する必要があるため、接続を確立します。
信頼性を確保するにはどうすればよいですか?
構造フィールドは信頼性のデータ構造の基礎を保証し、3 ウェイ ハンドシェイクは接続構造を作成する基礎となり、このようにして tcp の信頼性が間接的に保証されます。
3 回を超えるハンドシェイクによる接続の確立を理解する方法: 3 回を超えてハンドシェイクしても接続を確立できますが、不必要なリソースの無駄が発生します!
4 回手を振ることを理解する方法: 切断は双方の問題であり、両方の問題です。当事者は同意を得る必要があります
ここでのいわゆるデータを送信しないとは、ユーザー データを送信しないことを意味し、最下位層で管理メッセージの対話がないことを意味するものではありません。
データが送信され、切断する必要があることを tcp はどのようにして知るのでしょうか?
答えは、tcp は知りませんが、上位層が close (sock) を呼び出し、ファイル記述子を閉じることはデータが送信され、切断する必要があることを示します。切断されること。
4 回手を振ると状態が変化します:
積極的に切断する側、最終状態は TIME_WAIT 状態
、受動的に切断する側、最終状態は CLOSE_WAIT 状態
上記 2 つの状態は、両者がクライアントであるかサーバーであるかには関係ありません。 . 、TCP はピアツーピア プロトコルであるためです。
サーバー上に多数の close_wait がある場合:
1. サーバーにバグがあり、ファイル記述子を閉じるアクションが実行されない
2. サーバーに負荷がかかっており、クライアントにメッセージをプッシュしている可能性があります。その結果閉店が遅すぎる
4 つの手を振るアクションが完了しましたが、積極的に切断する側は一定期間 TIME_WAIT を維持する必要があります:
なぜですか? 通常どのくらい時間がかかりますか? また、なぜですか?
CLOSED 状態に戻るには通常 2 つの MSL が必要です!
なぜ必要なのでしょうか? to wait?
1 . これは、最後の ACK 応答が失われる可能性があるためです。一度失われると、タイムアウト再送が必要です。そのような待ち時間がないと、最後の ACK 応答が失われる可能性があります。一方の端では、接続が切断されていないと考え、情報、これはバグです。
2. 双方が切断しても、ネットワークにはまだパケットが残っています。残りのパケットが消失していることを確認してください。
MSL を理解する方法:
MSL は、TCP パケットの最大生存時間です。cat
/proc/ sys/net/ ipv4/tcp_fin_ timeout: 60 を介して ms1 の値を表示できます。
サーバーが時々ダウンする理由を理解する方法再起動されましたが、時々再起動できないバインドエラー:
サーバーがアクティブに切断されると、サーバーは TIME_WAIT 状態になり、現時点ではバインドを成功させることができません。
この問題を解決する方法:
setsockopt() を使用して、ソケット記述子オプション SO_REUSEADDR を 1 に設定します。これは、同じポート番号を持つが異なる IP アドレスを持つ複数のソケット記述子を作成できることを意味します。
10. 引き違い窓
スライディング ウィンドウを理解する方法:
まず、データが失われる可能性があるため、タイムアウト再送信メカニズムが存在します。これは、データが送信者によって送信された後に消去されず、送信バッファーに格納されることを決定します。送信バッファには罰金が科せられます:
写真が示すように
前半:送信済み、返信あり
中:スライディングウィンドウ→送信済み、返信なし!
奥:データ未送信
最後:データなし、スペースのみ
スライディングウィンドウの見方:
ウィンドウ サイズは最初にどのように設定され、将来どのように変更されますか?
win_ start = 0; win_ end = win_ start + tcp_ win -> 今後どのように移動しても、相手が受け入れられることを確認する必要があります。つまり、初期のスライディングウィンドウサイズ=相手の通知 自分の受容能力のサイズウィンドウは
左にスライドするのか? 必ず右にスライドするのか?
答えは、左にはスライドしない、かも
しれない右にスライドしますか、それとも同じままですか
? スライディング ウィンドウは変わりませんか? 大きくなりますか? 小さくなりますか? 変化の根拠は何ですか? 答えは、
スライディング ウィンドウは変わらない可能性があります。大きくなったり、小さくなったりします。変更の根拠は、相手が受け入れられるバッファ領域のサイズに基づいています! 受信
応答を確認するとき、送信したメッセージの確認ではない場合はどうすればよいですか?一番左ですが、真ん中と最後?
確認応答が受信されない場合は、
パケットが失われたことを意味します: パケット損失には 2 つのケースがあります:
1. データは失われていませんが、応答は失われました
。データは実際に失われています。
最初のケースの場合: 確認シーケンス番号の定義が ACK seq X + 1 であるため、X + 1 より前のすべてのデータが受信されたことを意味します win_start+X+1 2 番目のケースの場合
:データが本当に失われた場合、返される確認応答番号はまだ前の確認番号のままです。確認応答番号には 3 つの連続する同じ番号があることが規定されており、これにより再送信メカニズムが完全に後方にスライドします。スペースが足りないですか
?
送信バッファはカーネル内でリング構造として設定されます。
11.輻輳制御
輻輳制御を理解する方法:
クライアントがサーバーにメッセージを送信する際、1 ~ 2 メッセージが失われるという問題が発生する場合がありますが、このとき、再送メカニズムを使用して再送信できますが、クライアントがサーバーと同様に 1000 メッセージを送信すると、999 メッセージが送信されます。が失われます。現時点では、ネットワークに問題がある可能性があります。ネットワークに問題があるため、タイムアウト再送メカニズムを使用して大量のパケットをネットワークに送信することはできません。一度送信すると、ネットワークに問題が発生する可能性があります。したがって、ネットワークの問題には輻輳制御ソリューションを使用してください!
輻輳制御メカニズム:
TCP では、最初に少量のデータを送信し、パスを探索し、現在のネットワークの輻輳状態を調べて、データを送信する速度を決定するスロー スタート メカニズムを導入しています。
指数関数的成長モードでの輸送
クライアントがサーバーにデータを送信するとき、クライアントにはスライディング ウィンドウがあります。データを送信するとき、データはネットワークを通過し、データを受け入れるネットワークの能力を識別します。輻輳ウィンドウを使用します。輻輳ウィンドウの特性: 1.送信が開始されると
、
輻輳ウィンドウ サイズを 1 と定義します。
2. ACK 応答を受信するたびに、輻輳ウィンドウ + 1。 3.
データ パケットが送信されるたびに、輻輳ウィンドウとフィードバックされたウィンドウ サイズが比較されます。受信ホストによって小さい値が実際の値として使用されます。 送信ウィンドウのサイズ -> スライディング ウィンドウ = 最小 (サポート ウィンドウ、ウィンドウ サイズ (サーバーの受け入れ能力))
輻輳ウィンドウの増加率は指数関数的です:
スロー スタートとは、最初は遅いことを意味しますが、増加率は非常に速いため、制御するために輻輳ウィンドウは単純に指数関数的に増加することはできません。採用された方法: しきい値を使用します。
輻輳ウィンドウとして
、このしきい値を超えると、指数関数的に増加するのではなく、直線的に増加します。
TCP が開始し始めると、スロー スタートしきい値はウィンドウの最大値に等しくなります。
再送信がタイムアウトになるたびに、スロー スタートしきい値は元の値の半分になり、輻輳ウィンドウは 1 に戻ります。
要約:
少量のパケット損失の場合は、タイムアウト再送信をトリガーします。大量のパケット損失の場合は、ネットワークが混雑していると考えられます。TCP 通信が開始されると、ネットワークのスループットは徐々に増加します。ネットワークが混雑すると、スループットはすぐに低下します
。最終
的な分析では、輻輳制御は、TCP プロトコルがデータをできるだけ早く相手に送信する一方で、ネットワークに過剰な負荷がかかるのを避けるという妥協的な解決策です。
12.応答の遅れ
遅延応答の目的: ネットワークの混雑を考慮せずに、伝送効率を可能な限り向上させること
遅延応答の理解方法:
遅延応答の本質は、メッセージを受信したときに、すぐには応答せず、一定の時間間隔の後に応答することです。この方法の目的は、上位層がこの時間間隔中にバッファを削除できることです。データ、応答時のデータ今度は、サーバー側の受信バッファーが大きくなったことをクライアントに通知し、クライアントはデータ送信効率を向上させるためにさらに多くのデータを送信します。
例えば:
受信側のバッファが 1M であると仮定します。一度に 500K のデータを受信します。応答が即時であれば返されるウィンドウは 500K ですが、実際には処理側の処理速度が非常に高速である可能性があり、500K のデータが返されます
。 ;この場合、受信側の処理はまだ限界には程遠く、ウィンドウを拡大しても処理可能です;たとえば、
受信側が応答するまでにしばらく待機する場合、
、応答する前に 200 ミリ秒待機し、この時点で返されます。ウィンドウ サイズは 1M です。
すべてのパケットに遅延して応答できますか?
数量制限: N パケットごとに 1 回応答;
時間制限: 最大遅延時間を超えたときに 1 回応答;
具体的な数とタイムアウト時間はオペレーティング システムによって異なります; 通常、N は 2 です、タイムアウト時間は 200 ミリ秒です。各 n パケットに 1 回応答することで、サーバーがデータを受信したことを確認できることはどのように理解すればよいでしょうか? 理由
: 確認シーケンス番号の特性によって決まります。
現在の確認シーケンス番号を受信するということは、以前のすべての確認シーケンス番号を受信することを意味します。コンテンツを受け取りました!
13. 便乗返信
クライアントはサーバーにデータを送信し、サーバーはデータを受信した後もクライアントにデータを送信します データを送信する際には、最後にクライアントが送信したデータの応答を一緒に送信します このときの応答方法は応答のピギーバックと呼ばれる、本質的にデータ送信効率が向上します。
14. TCP のバイト指向ストリームを理解する
TCP ソケットを作成し、同時にカーネル内に送信バッファと受信バッファを作成します。write を
呼び出すと、データは最初に送信バッファに書き込まれます。
送信されたバイト数が長すぎる場合は、複数に分割 TCP データ パケットが送信されます。
送信されたバイト数が短すぎる場合は、バッファーの長さがほぼ同じになるまで最初にバッファー内で待機するか、データを受信するときに他の適切なタイミングでパケットを送信します
。 、データもネットワーク カードから駆動されます。プログラムがカーネルの受信バッファに到達すると、
アプリケーションは read を呼び出して受信バッファからデータを取得できます。
バッファの存在により、TCP プログラムの読み取りと書き込みを 1 つずつ一致させる必要はありません。たとえば、
100 バイトのデータを書き込む場合、write Once を呼び出して 100 バイトを書き込むか、write を呼び出すことができます。 100 回、毎回 1 ワードを書き込むセクション
。100 バイトのデータを読み取る場合、書き込み時に書き込み方法を考慮する必要はなく、一度に 100 バイトを読み取ることも、一度に 1 バイトを読み取ることもできます。 100回繰り返す。
15. 粘着袋問題
まず最初に、スティッキー問題における「パケット」とはアプリケーション層のデータパケットを指すことを明確にしておく必要があります。TCP
のプロトコルヘッダーには、UDPのような「メッセージ長」のようなフィールドはありませんが、フィールドは存在します。トランスポート層から見ると
、TCP は 1 つずつ来て、シーケンス番号に従ってバッファに配置されます。
アプリケーション層から見ると、目に見えるのは連続したバイトの連続です。このような一連のバイトデータを見ると、どの部分がどの部分から始まり、どの部分が完全なアプリケーション層
のデータパケットなのかがわかりません。では、スティッキー パケットの問題を回避するにはどうすればよいでしょうか? 肝心なのは、2 つのパケット間の境界を明確にすることです。
固定長パケットの場合は、毎回必ず固定サイズで読み取られるようにします。
可変長パケットの場合は、次のように指定できます。パケットのヘッダーの位置で、パケット ヘッダーの全長のフィールドに同意すると、パケットの終了位置がわかります。可変長
パケットの場合は、パケット間に明確な区切り文字を使用することもできます (アプリケーション層)プロトコルは、区切り文字がテキストと競合しない限り、プログラマー自身によって決定されます)。UDP プロトコルの場合、「スティッキー パケットの問題」もありますか?
UDP の場合、上位層がデータをまだ配信していない場合、UDP メッセージの長さはそのままです。同時に、UDP はデータをアプリケーション層に配信します。 1 つずつクリア データ境界が多数存在します。
アプリケーション層の観点から見ると、UDP を使用する場合、完全な UDP メッセージを受信するか受信しないかのどちらかになります。「半分」の状況は存在しません。
16.TCP例外
プロセスの終了:プロセスの終了によりファイルディスクリプタは解放され、FIN の送信は可能 通常のシャットダウンと変わりません
マシンの再起動:プロセスの終了と同じ状況
マシンの電源障害/ネットワークケーブルの切断:受信側は、受信すると、接続はまだ存在します 端で書き込み操作があり、受信側で接続がなくなったことを検出した場合、接続はリセットされます 書き込み操作がない場合でも、TCP 自体にはキープ機能が組み込まれています-alive タイマー, 定期的に相手がまだそこにいるかどうかを尋ねます. 相手がそこにいない場合は, 接続も解放します. さらに, アプリケーション
層の一部のプロトコルにもそのような検出メカニズムがあります. たとえばHTTP の長時間接続では、定期的に相手の状態を検出し、たとえば QQ が切断された後も定期的に再接続を試みます。
17.TCPの概要
信頼性保証:
チェックサム、シリアル番号、確認応答、タイムアウト再送、接続管理、フロー制御、輻輳制御 パフォーマンス向上:
スライディング
ウィンドウ、高速再送、遅延応答、ピギーバック応答
TCPベースのアプリケーション層プロトコル:
HTTP
HTTPS
SSH
Telnet
FTP
SMTP
18.TCP/UDPの比較
TCP は信頼性の高い接続だと述べましたが、TCP は UDP よりも確実に優れているのでしょうか? TCP と UDP の長所と短所は、単純かつ絶対的に比較することはできません。
TCPは、ファイル送信や重要なステータス更新など、信頼性の高い伝送に使用され、
UDPは、初期QQやビデオ伝送など、高速伝送とリアルタイム性が要求される通信分野に使用されます。 UDP はブロードキャストに使用できます。
結局のところ、TCP と UDP はどちらもプログラマのためのツールであり、いつ使用するか、どのように使用するかは、特定の需要シナリオに基づいて決定する必要があります。
19. UDP を使用して信頼性の高い送信を実現する方法
TCP の信頼性メカニズムを参照して、アプリケーション層で同様のロジックを実装します。
例:
データの順序を保証するために
シーケンス番号を導入し、ピアがデータを受信したことを確認するために確認
応答を導入し、一定時間が経過しても応答がない場合にデータを再送信するためにタイムアウト再送信を導入します。……
20. listen の 2 番目のパラメータを理解する
日常生活での例を挙げましょう。
ハイディラオを食べるとき、店内が満席で、客が絶え間なく来るときは、通常、客が座って列に並ぶためのテーブルが外にあります。
行列の本質は、誰かが食べ終わって帰ると、待っている客はすぐにハイディラオを食べることができるということであり、上司にとってはテーブルの稼働率が向上して収入が増えるが、あまりにも行列に並ぶのは好ましくない。長さ
listen の 2 番目のパラメータは、基本的にキューのサイズを維持するためのものです。
クライアントが接続を確立するリクエストをサーバーに送信するとき、現在の接続数がいっぱいの場合、接続の確立を要求しているクライアントはキューに追加されます。 queue. キューのサイズ listen の第 2 パラメータです
検証: listen の第 2 パラメータのサイズを 3 に設定します
このとき、同時に 3 つのクライアントを起動してサーバーに接続します netstat を使用して確認しますサーバーのステータス。すべて正常です。
しかし、4 番目のクライアントが開始されると、サーバーが見つかります。4 番目の接続のステータスに問題があります。
写真が示すように:
クライアントのステータスは正常ですが、サーバー側では ESTABLISHED ステータスではなく SYN_RECV ステータスが表示されます。
これは、Linux カーネル プロトコル スタックが TCP 接続管理に 2 つのキューを使用するためです。
1. セミリンク キュー (SYN_SENT および SYN_RECV 状態のリクエストを保存するために使用されます) 2. フル接続キュー (accpetd キュー) (確立された状態のリクエストを保存するために使用されますが、アプリケーション層
は accept を呼び出していません)
-connection queue 長さは listen の 2 番目のパラメータによって影響されます。
接続キューがいっぱいになると、現在の接続ステータスは引き続き確立状態に入ることができません。
このキューの長さは、上記の実験から知ることができます。 listen + 1 の 2 番目のパラメータ。
要約する
以上が TCP プロトコルの実装の全内容ですが、UDP プロトコルの実装と TCP プロトコルの実装の比較を読んだ後、TCP は信頼性を実現するためにかなりの数の戦略を採用していると思います。本日のご紹介はこちらです、また次回!