手入力のHTTPクライアント・サーバごっこで理解するHTTP

  • インゴットくん
    インゴットくん システムちーむ
  • このエントリーをはてなブックマークに追加
手入力のHTTPクライアント・サーバごっこで理解するHTTP

弊社はインターネットの制作会社なので、WebブラウザやWebサーバの動作に関する知識を深める必要があるのですが、現在ではWebブラウザ・Webサーバ共に既に高度な作り込みがされてしまっていて、実際にどのような通信がなされているかということに関心を払うことは少なくなってきています。

今回は、HTTP通信のうち、レイヤ7部分でのやりとりを、実際に人間が手入力で行うことで理解を深めてみたいと思います。

準備

CentOS 6サーバを用意して、rootユーザで以下のように入力し、今回のテストに必要なパッケージを入れます。


yum -y install nc telnet httpd
/sbin/service httpd start
iptables -I INPUT -m tcp -p tcp --dport 8080 -j ACCEPT

その後、一般ユーザに戻って、サーバにSSHターミナルを2窓で接続します。SSHターミナルは、上下に配置してみます。

二つの画面をTCPでつないでみる

下のSSHターミナルをクライアント(Webブラウザ)、上側をサーバ(HTTPサーバ)とみなして、それぞれで手入力用のコマンドを入力しましょう。

まず、上側のサーバ側ですが、特定のportをlisten(監視)する必要があるため、ncコマンドでportのlistenと標準入出力への接続を担当させます。


nc -l 8080

ターミナルの操作画像

これで、このサーバのlocalhost:8080をlistenし、クライアントと接続後は、標準入力をクライアントへ、クライアントから送信されてきた情報は標準出力に表示されます。

次に、下画面のクライアント側では、telnetコマンドを使って、tcpをlistenしているサーバのアドレス、listenしているポート番号を指定します。


telnet localhost 8080

ターミナルの操作画像

これで、レイヤ7より下の階層で3-way Handshakeが行われた後、TCPコネクションが確立します。下画面のクライアント、上画面のサーバがTCPで直結されました。

例えば、下の画面で「hoge[enter]」を入力すると、[enter]が押された時点で上の画面で「hoge[改行]」が表示されます。

ターミナルの操作画像

逆に、上画面で「fuga[enter]」を入力すると、[enter]が押された時点で下の画面で「fuga[改行]」が表示されます。

ターミナルの操作画像

なお、telnetの終わらせ方ですが、下画面にて、[Ctrl]+]を押します。その後、quit[enter]でtelnetから抜けます。

ターミナルの操作画像

上画面のncは、TCPのコネクションが切れるか、[Ctrl]+Cで終了です。

両方とも手入力でHTTPクライアント・HTTPサーバを演じてみる

ここまでは、クライアントとサーバを接続してみただけで、お互いに入力した文字が表示されるだけす。これは、「通信」とは言えますが、ルールがないので、意味のある交信にするには、いささか骨が折れます。

この状況から、より情報交換といえる状態にもっていくために、通信内容のルールを定めましょう。今回利用するHTTP 1.0というプロトコルは1996年に公開されたRFC1945として定められており(実利用ではHTTP 1.1として規定されたRFC7230~7235を使うことが多いです)、お互いにHTTPで通信を行うという申し合わせがあれば、意味のある情報通信となります。なお、申し合わせをする手段としては、一般的にポート番号(httpはポート80番を使って通信するという雰囲気がある)となります。

それでは、手入力でやってみましょう。先ほどと同様に、上画面でnc -l 8080、下画面でtelnet localhost 8080を入力します。

まず、下画面のクライアント側では、サーバにしてほしいことと、ほしいコンテンツのパスと、HTTP通信のプロトコル名を入力して、改行を2回打ちます。


GET / HTTP/1.0

ターミナルの操作画像

サーバ側では、それをうけて、


HTTP/1.0 200 OK
Content-Type: text/html
(空行)
<h1>ningen server desu.</h1>
<p>hello, World</p>
^D

と打ちますと、改行ごとにクライアント側のtelnetにそのまま表示されます。^Dは、[Ctrl]+Dで入力できる、入力が終わりという意味の制御記号です。これが入力されると、ncのTCPコネクションが切れ、コマンドプロンプトに戻ります。

ターミナルの操作画像

この一連の流れが、HTTPの仕様にのっとった交信となります。

人力WebサーバでWebブラウザをだましてみる

HTTPで通信すると取り決めがしてあれば、それを使うものであれば互換性があるはずなので、サーバをncにしたまま、クライアントをGoogle Chromeにしてみます。

まず、コンソールの上画面でncをlistenモードで起動させます。


nc -l 8080

次に、Google Chromeブラウザでhttp://192.168.33.10:8080/をアドレスバーに入れて接続します。

そのあと、コンソールの上画面に、先ほどのサーバ側の文字列を入れます。


HTTP/1.0 200 OK
Content-Type: text/html
(空行)
<h1>ningen server desu.</h1>
<p>hello, World!</p>
^D

すると、ブラウザにはこんな感じで表示されます。

ターミナルの操作画像

ここで人力サーバのレスポンスに関してお勉強


HTTP/1.0 200 OK
Content-Type: text/html
(空行)
<h1>ningen server desu.</h1>
<p>hello, World</p>
^D

のうち、最後の^Dは、ncコマンドへ入力の終了を伝えるものです。

最初の1行がステータスライン、その次の1行がレスポンスヘッダ、空行を挟んで後の2行がレスポンスボディです。改行コードは、HTTPではCR+LFと定められていますが、実運用ではLFで取り扱ってくれるようになっています。今回もLFを2回送信でブラウザ側が理解してくれています。

まとめ

  • 普段WebブラウザとWebサーバの間で行われている通信を、手入力でやってみました。
  • 手入力でやってみると、けっこう平気なことがわかりました。
  • HTTPのプロトコルのありがたみがわかりました。

なお、Webブラウザを人力でやった時サーバが受け取った文字数より、Google Chromeブラウザからアクセスしたときの文字数が圧倒的に多いのですが、これは、Webブラウザがリクエスト時のリクエストヘッダに、サーバにしてほしい要望を付加しているからです。また、本物のWebサーバにアクセスすると、レスポンスヘッダに付加情報がたくさん含まれているのが確認できます。

下図でいうと、


Server
Date
Content-Type
Content-Length
Connection

ターミナルの操作画像

ステータスライン・リクエストヘッダ・レスポンスヘッダは、Webアプリケーションを作るときにとても重要で、また知っているととても便利な仕組みが使えたりしますので、興味のある方はぜひ調べてみてください。

このエントリーをはてなブックマークに追加

インゴットくんが最近書いた記事

WRITERS POSTS もっと見る

他にもこんな記事が読まれています!

  • WEB
  • マーケティング
  • サーバー・ネットワーク
  • ライフスタイル
  • お知らせ