CommentsWebSocketとはHTTPはインターネットの基盤となるプロトコルですが、文書のやりとりを主旨とするため、かならずしも現在のニーズに応え切れているとは言えません。プッシュ通信ができないことは、今まで多くの技術者を悩ませてきました。WebSocketは、こうしたHTTPの不足を補い、サーバ・ブラウザ間でより安定的にデータをやり取りするための仕組みです。HTTPと違い、接続を永続的に維持するため、プッシュ通信が可能です。新しいプロトコルなので、サーバ側にもブラウザ側にも、専用の仕組みが必要となります。WebSocketが必要かWebサービスでチャットを作ることを考えてみましょう。HTTPにはプッシュ通信がありません。Aさんの発言を、Aさんの発言したタイミングでBさんとCさんに送信するにはどうしたら良いでしょう。この問題には、古来よりさまざまな対策手法が編み出されてきました。良く使われるのは、再読み込みボタンをつけたり、F5キーを押してもらったりして、サーバの情報を見に来てもらうというものです。このタイプのもっとも良くできたサイトでは、Ajaxが30秒おきにサーバを見に行って、画面が自動的に最新に更新されます。自動更新の間隔を30秒から10秒に縮めることはできても、リアルタイムにすることはできません。プッシュ通信ではないからです。チャットくらいならこれでも十分でしょう。Aさんの「おはよう」が届くのが、10秒後でも30秒後でも、大した問題にはならないことがほとんどだからです。ゲームならどうでしょうか。対戦相手のいる艦隊ゲームです。敵の場所が10秒おきにしか更新されないのでは、レーダーなしでUボートを相手にするようなものです。次の10秒後にお知らせされるのは、敵の位置ではなく、あなたの艦隊の目も当てられないような被害状況かも知れません。した用途にはFlashを使うのが一般的ですが、高性能化するスマートフォンでもFlashはやはり重く、iOSに至っては未実装です。WebSocketはほぼすべてのモダンブラウザで動作します。iOSが採用しているモバイルSafariでも動くのです。長くなりましたが本題です。WebSocketのサーバ側の実装は、HTTPで言うところのApacheやIISといったメジャーなサーバプログラムやフレームワークは無いのですが、WebSocket自体がそれほど大がかりな仕組みではないので、それならいっそ作ってしまえというのが今回の趣旨です。node.jsやPHPを使って作られたものがすでにありますので、手っ取り早くやるにはこうしたオープンソースを利用するのが良いでしょう。全体の流れRFCを参考に作っていきます。http://tools.ietf.org/html/rfc6455WebSocket通信の、おおまかな流れは、以下のようになります。自由にデータを送り合うハンドシェイクパートは、HTTP通信のリクエスト・レスポンスに似たやり取りです。接続の確立後はWebSocket独自形式に切り替わり、フレームデータをお互いに送り合う形となります。ハンドシェイク通信は、ブラウザからの以下のようなハンドシェイク要求で始まります。13サーバはこれに応え、下記のような応答を返します。chatまずは通信の基礎となる、ソケット通信部分の実装から作っていきます。ここはWebSocketというよりはいわゆるソケット通信のとこなんで、あまり深追いはしません。ちなみにソースコードはC++です。新規接続を親プロセスで待ち受け、接続が確立したら子プロセスにフォークする、という仕組みにします。新規接続用のcurr_sock、子プロセス用のfork_sock、2つのソケットを使いますので、これらを初期化します。curr_sockは待ち受け用なので、IPアドレスにバインドしておきます。次に、先ほど作った待ち受け用のソケットを接続待ち状態にします。定期的にメッセージの到着を調べるため、select()関数をwhileループで回します。メッセージが到着している場合は、この接続を子プロセスにforkします。メッセージの解析などの後続処理は子プロセスで行います。親プロセスはまたwhileループの最初に戻り、メッセージの到着を調べる作業に戻るというわけです。接続が確立されて子プロセスに処理が回ってきました。ハンドシェイク要求の受付を行います。ハンドシェイクは最初に接続してきたときだけで、接続確立後は行いませんので、子プロセス内で最初の1回だけ通るように書いておきます。ブラウザからのハンドシェイク要求は、HTTPのGETリクエストに似ています。GETでリクエストされている”/”以降の部分を、WebSocketではプロトコルと呼んでいて、クライアントがどんなサービスを要求しているかを知ります。サーバアプリ側では、これを判別することで、要求に応じた処理や応答を返す仕組みが作れるわけです。通常のWebサービスでも”/chat”をリクエストすればチャット画面が表示され、”/poker”をリクエストすればポーカーのプレイ画面が表示され、ということを期待しますね。それと同じような振る舞いを、WebSocketでも想定しているということです。”Sec-WebSocket-Key”パラメータの値が、ハンドシェイクでやり取りされるキーとなります。この値はブラウザがランダムに生成してきたものです。サーバ側では、この文字列にGUID(”258EAFA5-E914-47DA-95CA-C5AB0DC85B11′′)を付加して、SHA1でハッシュ化し、base64エンコードして、ブラウザに応答キーとして返します。ブラウザから送られてきたキーが”dGhlIHNhbXBsZSBub25jZQ==”であった場合、”dGhlIHNhbXBsZSBub25jZQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11′′をSHA1のハッシュ関数にかけます。これをbase64エンコーディングすると、”s3pPLMBiTxaQ9kYGzzhZRbK+xOo=”となります。したがって、レスポンスパラメータ”Sec-WebSocket-Accept”には、”s3pPLMBiTxaQ9kYGzzhZRbK+xOo=”をセットします。レスポンスパラメータの”Sec-WebSocket-Protocol”はオプションで、プロトコルが複数あって指定する必要がある場合に、セットするようです。これは良く分からないのですが、ブラウザから”/chat”と要求されたら、レスポンスにも”/chat”と返す、という利用方法では無いようです。実際、ブラウザからのリクエスト通りにレスポンスをセットしたら、ブラウザ側(Chrome)でハンドシェイク失敗になってしまいました。今回のソースではこのパラメータ自体を返さないようにしています。※ハンドシェイクの処理は80行目までです。長くなってしまったので、その2へ続きます。コメントをキャンセルメールアドレスが公開されることはありません。InkThemes.。