TCP/IP におけるクライアントとサーバーの通信
本記事は、curl などを使って example.com のデータを取得するときに、TCP のスリーウェイハンドシェイクがどのように行われるか、また、レスポンスがリクエスト時と同じ接続で返されるかについて整理したものです。
- 接続の確立は、クライアントが SYN を送信することで始まります
- レスポンスは、リクエストを送信した接続と同じ接続で返されます
1. 接続の確立
curl で https://example.com/ を取得は次の順序で進みます。
- DNS で
example.comの IP アドレスを解決します。 - クライアントが SYN を送信します。
- サーバーが SYN/ACK を返します。
- クライアントが ACK を返し、TCP 接続が確立します。
- HTTPS の場合は、この時点で TLS ハンドシェイクを行います。
- HTTP リクエストを送信します。
SYN を送り出すのはクライアント側(curl を実行しているマシン)です。
サーバー側は listen 状態で待機しており、SYN を受信して応答を返します。
SYN、SYN/ACK、ACK による TCP 接続をスリーウェイハンドシェイクと呼びます。
2. レスポンスと接続の関係
レスポンスは、リクエストの送信に使った接続と同じ接続で返されます。
TCP は双方向(全二重)の通信路です。そのため、1 本の接続の中で、クライアントからサーバーへリクエストが流れ、サーバーからクライアントへレスポンスが流れます。
この接続は、次の四つの組で識別されます。
| 要素 | 内容 |
|---|---|
| クライアントの IP アドレス | 通信を開始した側のアドレス |
| クライアントのポート番号 | OS が自動的に割り当てる一時ポート |
| サーバーの IP アドレス | 接続先のアドレス |
| サーバーのポート番号 | HTTP は 80、HTTPS は 443 |
レスポンスは、この組の送信元と宛先を入れ替えた向きで返されます。
3. 補足事項
3.1 接続の終了
レスポンスの送受信が終わると、通常は FIN/ACK のやり取り(いわゆる四ウェイハンドシェイク)で接続を閉じます。ただし、HTTP/1.1 の keep-alive や HTTP/2 では、同じ接続を再利用して複数のリクエストを送受信することもあります。
3.2 HTTP/3 の場合
HTTP/3 は TCP ではなく、UDP 上の QUIC を使います。そのため、スリーウェイハンドシェイクは行われません。なお、curl は既定では基本的に HTTP/2 または HTTP/1.1 を使用します。
3.3 確認方法
接続の様子は、次の方法で確認できます。
curl -v https://example.comを実行すると、通信の過程が表示されます。Connected to ...の行は、TCP 接続が確立した後であることを示します。- パケットレベルで SYN、SYN/ACK、ACK を観察したい場合は、
tcpdumpや Wireshark を利用します。