- Published on
TCPがどのように機能するか
- Authors
- Name
- あやき
- @ayaki2325
TCPがどのように機能するか自信を持って説明できるようになるための記事です。
クライアントとサーバーがデータをやり取りする流れをまとめます。
対象読者は、TCPを一度でも学んだことがある人です。
具体的には、TCPに関する入門書を読んだり、基本情報技術者試験のネットワーク分野を学んだりした経験がある人です。
クラウドサービス利用時などTCPの知識が役に立つ場面は多いので、ぜひ最後までご覧ください。
全体像
クライアントとサーバーがデータをやり取りする流れは以下です。
- ソケットを作成する
- 接続する
- データを送受信する
- 切断してソケットを抹消する
ソケットを作成する
クライアントとサーバー共に、以下流れでソケットを作ります。
- ソケットひとつ分のメモリー領域を確保して、そこに初期状態であることを記録する。
- そのソケットを示すディスクリプタをアプリケーションに通知する。
ソケットを作るタイミングは、クライアントとサーバーで異なります。
クライアントはユーザーが何らかのアクションをとり、サーバーにアクセスする動作を始めるときにソケットを作ります。
サーバーはアプリケーションが動き始めたときにソケットを作ります。
接続する
クライアントとサーバー双方のソケットが作れたら、それらを接続します。
- [サーバー] ソケットにポート番号を記録する。
- [サーバー] ソケットに接続待ちの状態であるという制御情報を記録する。
- [サーバー] 接続を受け付ける処理を実行して休止。
- [クライアント] TCPヘッダーを作ってサーバーに送信する。色々なフィールドがある1が、重要なのは以下。
- 送信元ポート番号: ソケット作成時に割り当てられた値
- 宛先ポート番号: HTTPなら 80
- SYNビット: 1
- シーケンス番号: 初期値
- ウインドウ: 受信用メモリーの空き容量
- [サーバー] TCPヘッダーの宛先ポート番号に該当する接続待ちソケットを見つける。
- [サーバー] そのソケットをコピーして新しいソケットを作り、そこに送信元のIPアドレスやポート番号、シーケンス番号の初期値、ウインドウの値など、必要な情報を記録する。同時に、送信バッファや受信バッファとして使うメモリー領域を確保する。
- [サーバー] TCPヘッダーを作ってクライアントに返信する。重要なのは以下。
- 送信元ポート番号: クライアントから受信したTCPヘッダーの宛先ポート番号と同じ
- 宛先ポート番号: クライアントから受信したTCPヘッダーの送信元ポート番号と同じ
- SYNビット: 1
- ACKビット: 1
- シーケンス番号: 初期値
- ウインドウ: 受信用メモリーの空き容量
- [クライアント] TCPヘッダーを調べてサーバー側の接続動作が成功したことを確認する。
- [クライアント] ソケットにサーバーのIPアドレスやポート番号、接続完了を表す制御情報などを記録する。
- [クライアント] ACKビットを1にしたTCPヘッダーをサーバーに返信する。
データを送受信する
Webの場合は、まずクライアントからサーバーへリクエストを送ります。
- [クライアント] シーケンス番号を記載したTCPヘッダーとデータをサーバーに送信する。
- [サーバー] 届いたパケットの送信元IPアドレス、送信元ポート番号、宛先IPアドレス、宛先ポート番号から該当するソケットを判断する。
- [サーバー] ACK番号とウインドウを記載したTCPヘッダーをクライアントに返信する。
ポイントは以下です。
- パケットが届いたことをACK番号を使って確認する
- 毎回返信するピンポン方式では効率が悪いので、ある程度まとめて返信するウインドウ制御方式が使われる
- データをすべて送り終えるまで、上記流れを繰り返す
リクエストがすべてサーバーに届いたら、次はサーバーからクライアントへレスポンスを送ります。
その際は、基本的に上記流れが逆になるだけです。
切断してソケットを抹消
ここでは、サーバーから切断フェーズに入るとします。
- [サーバー] FINビットを1にしたTCPヘッダーをクライアントに送信する。同時に、ソケットに切断動作に入ったという情報を記録する。
- [クライアント] ACK番号を記載したTCPヘッダーをサーバーに返信する。
- [クライアント] FINビットを1にしたTCPヘッダーをサーバーに送信する。同時に、ソケットに切断動作に入ったという情報を記録する。
- [サーバー] ACK番号を記載したTCPヘッダーをクライアントに返信する。
この後は、しばらく待ってから、ソケットを抹消します。
最後までご覧いただき、ありがとうございました。