IP 通信の代表格、Web サーバのサイト閲覧に関する HTTP プロトコル通信の流れを見ていきます。この記事で扱うバージョンは HTTP/1.0 および HTTP/1.1 です。
HTTP のバージョン変化、および最新バージョン HTTP/3 の仕組みについては以下を参照下さい。
DNS による名前解決
PC はまず DNS による名前解決を行います。例えば www.yahoo.co.jp へアクセスしたいとき、PC に設定されている DNS サーバに対して www.yahoo.co.jp の IP アドレスを問い合わせます。
DNS サーバは社内からのみ利用可能な社内構築サーバもあれば、インターネット上で公開されているものもあります。
8.8.8.8 というのは Google が無償で提供している有名な DNS サーバです。また、CDN で有名な CloudFlare も 1.1.1.1 という IP で公開しています。DNS の仕組みについては以下をご参照下さい。
なお、ブラウザにプロキシ設定されている場合はプロキシサーバが DNS で名前解決するのでシーケンスが異なります。これについては以下をご参照下さい。
TCP コネクション確立
次に、www.yahoo.co.jp の IP アドレスに対して、TCP コネクションを確立します。
まずは TCP syn パケットを PC から Web サーバへ送り、Web サーバからは TCP syn/ack パケットを返します。
そして PC から TCP ack パケットを送ります。これでコネクション成立となります。
このやり取りをスリーウェイハンドシェイクと呼びます。
http GETメソッドによるhtmlファイル要求(リクエスト)
PC は TCP ack を送ったら相手の反応を待たず、PC からサーバへ http GET メソッドによるリクエストの通信を行います。GET メソッドはサーバからファイルをダウンロードする命令です。
HTTP のバージョン 1 および 1.1 は ASCII ベースのプロトコルです。やり取りのすべてが ASCII コードで行われます。
例えば TCP のペイロードの最初に ASCII 文字で
という文字列から始まる、http 規格に則った文章を送ります。
/ の後には本来 /index.html などの要求するファイル名が入るのですが、たいていのサイトは / だけ要求すれば、サーバ側でデフォルト設定されているファイルを返すようになっています。
HTTP/1.0 は『HTTP のバージョン 1.0 による要求』という意味です。
なお、見出しでは「html ファイル要求」としていますが、実際には txt でも pdf でも zip でも wmv でも、ファイルの種類は何であっても要求可能ですし、何でもダウンロード可能です。(MIME による ASCII ベース以外のデータ送信への対応)
メソッドや次に出てくるステータスコードについては以下をご参照下さい。
HTTP ステータス応答(レスポンス)コードと要求したファイルの送信
上記要求をするとサーバから PC へ
という文字列と共に、要求したファイルが送られてきます。
(『HTTP/1.0 200 OK』と返ってくる場合もありますが、サーバ側の環境に依ります。RFC2145 に記載がありますが、ここでのバージョンは能力として 1.1 の機能を有することを示してはいますが、1.0 クライアントからのリクエストには、1.0 が理解できる応答をします。)
この時、ファイルサイズが例えば 1460 Byte 以上の MSS 値に収まりきらない量の通信が必要な場合は、サーバの OS が TCP セグメンテーションにより分割して複数パケットにして送ります。(IP のフラグメンテーションではなく、TCP セグメンテーション)
200 は HTTP の GET メソッドが成功したことを意味する、ステータスコードです。
telnet でパケットの流れを把握する
http/1.0 および http/1.1 は通常はブラウザを使って行いますが、ASCII ベースのプロトコルなので telnet を使って行うこともできます。
例えば windows7/8/10 に telnet クライアントを追加し (30 秒でできる telnet クライアント機能を追加する方法はこちら)、コマンドプロンプトで以下を打つと分かり易いです。(TeraTerm で同様の手順を試しても OK です)
C:\> telnet milestone-of-se.nesuke.com 80
で接続した後 (milestone-of-se.nesuke.com を DNS で名前解決し、そのIPアドレスへ TCP 80番ポートで接続する、という意味)、
> GET /http.txt HTTP/1.0 > Host: milestone-of-se.nesuke.com
と打ち、(大文字小文字の区別をつけること。コピペでもOKです。)Enter を3回打つと、やはり ASCII 文字列で以下の画面が返ってくるはずです。
これは、Web サーバ上に「http.txt」というファイルを配置してあり、GET メソッドによりこのファイルをダウンロードしてきているのです。このファイルの具体的中身は最後のに2行のみです。それまでの『HTTP/1.1 200 OK ~ Accept-Ranges: bytes』の行は、HTTP ヘッダです。
ブラウザで https://milestone-of-se.nesuke.com/http.txt にアクセスすると http.txt のファイルの実態が分かります。
なお、入力する文字列を間違えると、milestone-of-se.nesuke.com のサイトは 400 Bad Request を返します。これは他のサイトでも大抵同じです。telnet が文字入力するたびに通信を送っているためです。つまり、1文字だけを TCP セグメントに乗せて送る、ということを繰り返し行っているのです。
このように、http では ASCII 文字列で人間に理解しやすい形式で通信がなされています。このような通信は他にも SMTP や FTP、SIP などがあります。
一方、DNS ではパケットだけを見ても ASCII 文字列 (人が理解しやすい形式) は無く、いわゆるバイナリ形式 (人が理解しづらく、機械が処理しやすい形式) で通信を行います。何番目の bit がどのような意味か、というのがあらかじめ規格で決められているのです。
http 通信をパケットキャプチャで見てみる
Wireshark という無料ソフトでネットワークに流れるパケットを閲覧できます。
最近は https 通信が当たり前で、http 通信のできるサイトは少なくなってきました。このページも基本は全て https ですが、以下 URL だけは例外的に http 通信ができるようにしています。
[ http://milestone-of-se.nesuke.com/http.txt ]
上記 URL にアクセスしたときの通信をパケットキャプチャで見てみます。クライアント = 192.168.100.100, サーバ = 157.112.150.6 です。
取得したパケットキャプチャを "tcp.port == 11699" でフィルタして表示しています。なので、1つの TCP コネクションのみが表示されています。
最初の 3 行が 3way Handshake です。そしてその後にクライアントからサーバに対して http 通信(GETメソッド)を発行しています。
下の左側の領域はキャプチャした内容を 16進数 で表示しています。青になっている部分が TCP のペイロード(つまり http の始まり)です。47 は ASCII で G を意味します。同様に 45 は E, 54 は T です。右下の領域は ASCII 変換で表示されていて、青色部分で "GET" という文字列になっているのが分かります。これが GET メソッドです。
その次に ACK を挟んで http レスポンスコード200 OK が返されています。
それに対しても ACK が返され、数秒経った後にサーバから [FIN, ACK] でサーバ⇒クライアントの方向のコネクションを閉じています。そのまた数秒後にクライアントから [FIN, ACK] でクライアント⇒サーバの方向のコネクションを閉じています。
なお、http のヘッダとボディの境目は改行コード \n\r (0x0d0a) が2連続出たところです。リクエスト ( GET メソッド等 ) にはボディはありません。レスポンスについては一般的には具体的なダウンロードするファイル ( html や txt 等なんでも ) の中身がボディに含まれます。
httpsの中身を見るには
https は暗号化されているため、そのままではメソッドやレスポンスコード等は見れません。ですが、以下の方法を使えば簡単に見ることができます。
ただし、ブラウザではなく独自アプリケーションで通信する場合はうまく動作しない場合があるのでご注意下さい。
コメント