WiresharkでWebSocket通信をパケットキャプチャしてみた(WebSocketの接続)
Wiresharkはバージョン1.8.0から対応プロトコルにWebSocketが追加されていて、WebSocketの通信はWebSocketと表示される
そんなわけで、早速パケットを覗いてみる。
使った環境は「WebSocketでEchoServerをつくる(Jetty8編)」のもの。
つまり、以下。
サーバ:Jetty 8.1.8.v20121106
クライアント:Google Chrome 24.0.1312.52
まずは、WebSocketのコネクション接続時。と言っても、ここはHTTP通信で行われるので、普通にHTTPリクエストとHTTPレスポンスだったりする。
HTTPリクエストはこんな感じ。
GET /WebSocket_Jetty/EchoServlet HTTP/1.1 Upgrade: websocket Connection: Upgrade Host: 192.168.1.5:8080 Origin: http://192.168.1.5:8080 Pragma: no-cache Cache-Control: no-cache Sec-WebSocket-Key: 30NeuZ+L6XOBboj/l7m/tg== Sec-WebSocket-Version: 13 Sec-WebSocket-Extensions: x-webkit-deflate-frame
今回の接続先は "ws://192.168.1.5:8080/WebSocket_Jetty/EchoServlet" でJavaScriptで
var ws = new WebSocket("ws://localhost:8080/WebSocket_Jetty/EchoServlet");
と書くと上のようなHTTPリクエストが送信される。
では、HTTPリクエストの内容をもうちょっと見てみる。
GET /WebSocket_Jetty/EchoServlet HTTP/1.1 Host: 192.168.1.5:8080 Pragma: no-cache Cache-Control: no-cache
このあたりは通常のHTTPと変わらない。普通のGET。
"no-cache"の指定がされているが、RFC6455ではキャッシュについての記述は見当たらないので、あってもなくてもいいのではないかと。
Upgrade: websocket Connection: Upgrade
この2つは必須のヘッダ。"Upgrade"には"websocket"、"Connection"には"Upgrade"を必ず指定する。
Origin: http://192.168.1.5:8080
ブラウザからのリクエストの場合は必須。ブラウザ以外の場合はあってもなくてもよい。超簡単に言うと、このWebSocket接続のリクエストを投げたJavaScriptをダウンロードしたオリジン。
今回は、"http://192.168.1.5:8080/WebSocket_Jetty/index.html" の中に書かれたJavaScriptがWebSocketの接続をしているので、上の値が設定されている。オリジンの詳細についてはRFC6454 "The Web Origin Concept"を参照。
Sec-WebSocket-Key: 30NeuZ+L6XOBboj/l7m/tg==
これも必須。ランダムに4バイトの値を作成し、さらにbase64でエンコードした値が設定される。ランダム値なので、この値は毎回違うものが使用される。
Sec-WebSocket-Version: 13
WebSocketのバージョンで、必須のヘッダ。現在のRFC6455では、必ず"13"を指定。
Sec-WebSocket-Extensions: x-webkit-deflate-frame
オプションのヘッダ。どうもChromeは "x-webkit-deflate-frame" を入れるらしい。
"x-webkit-deflate-frame"はWebSocketのフレームを圧縮するものだが、少なくともJettyやTomcatでは使えないので無視しておこう。
他にも "Sec-WebSocket-Protocol" なんていうオプションのヘッダもRFC6455にはあるが、今回は使ってないので、また今度。
以上でHTTPリクエストは終了し、HTTPレスポンスはこんな感じでやってくる。
HTTP/1.1 101 Switching Protocols Upgrade: WebSocket Connection: Upgrade Sec-WebSocket-Accept: fdJzSVExohGlkkwXcc59Jq1yEkE=
では、詳細を見てみよう。
HTTP/1.1 101 Switching Protocols
ステータスコードなので、当然、必須ヘッダ。サーバ側がWebSocketの接続を受け入れる場合のステータスコードは"101"。
Upgrade: WebSocket Connection: Upgrade
リクエスト同様、必須ヘッダ。
Sec-WebSocket-Accept: fdJzSVExohGlkkwXcc59Jq1yEkE=
必須ヘッダ。この値は以下の手順で作られる
- 1. リクエストの中にあった"Sec-WebSocket-Key"の値と、固定の文字列"258EAFA5-E914-47DA-95CA-C5AB0DC85B11" を連結する。
- 2. その値のSHA-1ハッシュを算出する。
- 3. そこから得られる20バイトをbase64でエンコードする。
ここまでのやり取りでWebSocketの接続が完了。
データ送受信のパケットキャプチャは次回にでも。