シェルスクリプトマガジン

もしインターネットの1秒が1年だったら 第3回(vol.49掲載)

4月28日 午後9時45分 HTTPレスポンスの最初のパケット送信

お手のものと言いながら、なんだかんだ言って半日仕事になってしまいましたが、ともあれサーバーちゃんはクライアントちゃんが尋ねてきた質問に答えるためのデータを見つけ出しました。サーバーはクライアントからのリクエストを元に処理を行い、HTTPレスポンスを返します。

これはステータス行(status line)とHTTPヘッダーとメッセージ本体で構成されます。

ステータス行には、レスポンスの状態を表すHTTPステータスコードなどが記されています。今回はリクエストされたリソースが正常に見つかったので、OKを意味するステータスコード200を返します。
HTTPヘッダーでは、その他のレスポンスの付加的なメタ情報などを表現します。今回のレスポンスには、処理日時(Date)、サーバー情報(Server)、キャッシュ関連の情報(Last-Modified,ETag)、本文のメタ情報(Content-Length, Content-Type) などが含まれています。
そして、通信の主目的であるメッセージ本体がその後に続きます。今回転送するデータは100KBと、とてもTCPセグメントやIPパケットやイーサネットフレームに収まる大きさではないので、必然的に複数のセグメントに分割されて転送されます。このセグメントの大きさはTCPコネクション時のSYNパケットに指定されたMSS(Maximum Segment Size)オプションによって決定されます。
今回の通信経路はおそらくイーサネットによって断片化することなく最後まで伝達できる経路であり、経路MTU(Path Maximum Transmission Unit)はイーサネットフレームの最大サイズである1500バイト、実際に転送されるデータセグメントはここからIPヘッダ20バイトとTCPヘッダ20バイトを除いた1460バイトとなるため、一般的にMSSは1460バイトに設定するのが標準的です。PPPoEなどではこれより若干小さな値になるので、断片化を防ぐためには個別に設定が必要です。
今回サーバーが送信したデータは100KB(102400バイト) のメッセージ本文に275バイトのヘッダーを付与したHTTPレスポンスなので、これをTCPセグメントで送出するには(102400+ 273) / 1460 = 70.3… より最低71個のパケットが必要となります。測定結果を見ると、送出したパケットはきっちり71個のTCPセグメントに分けられていました。
そういうわけで、サーバーちゃんはクライアントちゃんの質問に答えるための71枚の手紙を用意しました。これを一気にポストに投函すると重量オーバーで郵便局員に怒られてしまうので、まずは1枚目から、順番にポストに入れていきます。
まあ、往復する回数が増えるぶんかえって郵便局員の負担は増えるんですが、それはそれ、これはこれです。

「郵便屋さん、頑張ってねー」

5月11日 午後2時4分 HTTPレスポンスの最初のパケット受信

ゴールデンウィークが終わり、7月中旬の海の日まで祝日のない地獄の2ヶ月間が始まるころ、ようやくサーバーちゃんからメッセージ本文を含む最初の手紙が届きます。
ゴールデンウィークではしゃぎすぎてグダっていたクライアントちゃんも、3週間ぶりのサーバーちゃんからの手紙で生き返りました。今回の通信で用いる暗号は、鍵長256ビット、ブロック長128ビットのAES256なので、1つのパケットに平均11個強のブロックが含まれていることになります。
実際には暗号利用モード*1によってオーバーヘッドが生じるため、必ずしも送られてきたパケットをすぐに利用できるとは限らないのですが、少なくともこの最初のパケットの段階で、クライアントちゃんがメッセージ本文の最初の部分を読み始めることができることは間違いないでしょう。
クライアントちゃんは、待ちに待った手紙を解読しながら喜んで読み始めました。通信開始してから130日も経っていますが、クライアントちゃんが年明けと同時に感じたサーバーちゃんへの思いは少しも色褪せていません。物理的には1300km離れているサーバーちゃんの存在も、今ではとっても近くに感じます。

*1 今回の場合はGCM(Galois/Counter Mode)。