FC2ブログ

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

WebSocket (Version8, hybi-10) のプロトコルとか

WebSocketを使ってみた時のメモ

■ WebSocketとは
ウェブサーバーとブラウザの双方向通信のための規格です。
例えば、従来のチャットサイトだと、相手が発言したとしても、リアルタイムでメッセージが更新されるわけではなく、メッセージを見るためには、ページを更新する必要があります。
ブラウザ → サーバー → ブラウザ
このような一連のやり取りによって、内容を更新するため、ブラウザから更新を要求する必要があります。

WebSocketの技術を使うことで、一旦WebSocket接続をしてしまえば、
サーバー → ブラウザ
というようにサーバーからブラウザに向けてデータを送信できるため、リアルタイムでブラウザにメッセージを表示させることができます。

■ WebSocketのバージョン
WebSocketは、登場して2年程度しか経っていないため、これまで何度も改訂がされてきました。
プロトコルの仕様が変わっていて、それぞれのプロトコルに互換性が無かったりするので、
サーバーとブラウザでそれぞれ互換性が無いと通信することができません。
よって、サーバーが古いバージョンのまま更新されないと、新しいブラウザでは動作しないので注意が必要です。
例えば、Firefox 7やChrome 14 ではWebSocketのバージョンは8(ドラフトhybi-10)です。
(WebSocketのバージョンとドラフトのバージョンが違う場合があります…)

■ サーバー・クライアントの種類と対応状況
有名どころは、Wikipediaにまとめてあります
Wikipedia - WebSocket

stackoverflowのこのページも参考になると思います
What browsers support the WebSocket API?

■ WebSocketプロトコル

まず、WebSocketプロトコルの仕様は、IETFのサイトで確認できます
The WebSocket protocol

WebSocket APIの仕様は、W3Cのサイトにあります
The WebSocket API



以下の画像は、Firefox 7 でWebSocketサーバーに接続して、メッセージを送受信してクローズするまでのプロトコルです。

websocket ASCII

これをバイト列で表すと、このようになります。

websocket バイト
赤文字の部分は、ブラウザからサーバーへの通信、青文字はサーバーからブラウザです

◆ ハンドシェイク
クライアント、サーバー間のウェブソケットを確立するためのやり取り
Note: 以下は、WebSocketバージョン8 (draft-ietf-hybi-thewebsocketprotocol-10で規定)
のプロトコルで、古いバージョンのプロトコルと異なります。


◇ ハンドシェイクリクエスト (ブラウザ → サーバー)
GET /chat HTTP/1.1
Host: 192.168.11.3:58787
User-Agent: Mozilla/5.0 (Windows NT 5.1; rv:7.0.1) Gecko/20100101 Firefox/7.0.1
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: ja,en-us;q=0.7,en;q=0.3
Accept-Encoding: gzip, deflate
Accept-Charset: Shift_JIS,utf-8;q=0.7,*;q=0.7
Connection: keep-alive, Upgrade
Sec-WebSocket-Version: 8
Sec-WebSocket-Origin: null
Sec-WebSocket-Extensions: deflate-stream
Sec-WebSocket-Key: WIY4slX50bnnSF1GaedKhg==
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket



不要な部分を削除すると、
GET /chat HTTP/1.1
Host: 192.168.11.3:58787
Connection: keep-alive, Upgrade
Sec-WebSocket-Version: 8
Sec-WebSocket-Origin: null
Sec-WebSocket-Extensions: deflate-stream
Sec-WebSocket-Key: WIY4slX50bnnSF1GaedKhg==
Upgrade: websocket



◇ ハンドシェイクレスポンス (サーバー → ブラウザ)
上のハンドシェイク要求を受け取ると、サーバーは下の応答を返します。

HTTP/1.1 101 Switching Protocols
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Accept: HLsuiHpqiMRADWIpBmfKuNWkpHk=


サーバーは、リクエストがウェブソケットのハンドシェイク要求であり、かつ対応しているバージョンである場合に上のような応答を返します。サーバーとブラウザ間でWebSocket接続が確立され、データのやり取りができるようになります。
リクエストが不正などの場合は、HTTP/1.1 400 Bad Request などの応答が返され、WebSocketの接続に失敗します。

Sec-WebSocket-Acceptヘッダの "HLsuiHpqiMRADWIpBmfKuNWkpHk=" という文字列は、このように作られます:
リクエストのSec-WebSocket-Key: WIY4slX50bnnSF1GaedKhg==の
"WIY4slX50bnnSF1GaedKhg=="という文字列に、
"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"という文字列を連結して
"WIY4slX50bnnSF1GaedKhg==258EAFA5-E914-47DA-95CA-C5AB0DC85B11"とします。

Note: 接続の度にSec-WebSocket-Keyの値は異なりますが、連結する"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"という文字列は変わりません。

連結してできた文字列をSHA-1でハッシュをとります。
得られた20バイトのバイト列を、base64でエンコードすることによって、Sec-WebSocket-Acceptヘッダの値が求まります。
プログラムではこんな感じです:
MAGIC = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
s = Sec-WebSocket-Keyの値;
Sec-WebSocket-Acceptの値 = base64encode( sha1( s + MAGIC ) );


これでWebSocketを用いてやり取りができるようになりました!



長くなったので続きは後日、別の記事で書くかもしれません。
スポンサーサイト

コメントの投稿

非公開コメント

プロフィール

にんじん

Author:にんじん

最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ
検索フォーム
RSSリンクの表示
リンク
ブロとも申請フォーム

この人とブロともになる

QRコード
QR
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。