たまたまWebをさまよっていたら、WebSocketの話が目についたので調べてみた。まあ、HTTPに比べると、一旦リンクを張ってしまえばサーバ側からも通信ができるってのが美味しいところ。
で、ブラウザがWebSocketをサポートしているか確認することができるサイトが
http://www.websocket.org/echo.html
なのですが、ここには自分でHTMLを書いて確認したい場合のためのコードが置いてあったりします。で、これを試してみると・・・テキストエディタに貼り付けたら1行になってしまいました(T_T)
整形しなおしたものをここに置いておきます。
<!DOCTYPE html> <meta charset="utf-8" /> <title>WebSocket Test</title> <script language="javascript" type="text/javascript"> var wsUri = "ws://echo.websocket.org/"; var output; function init() { output = document.getElementById("output"); testWebSocket(); } function testWebSocket() { websocket = new WebSocket(wsUri); websocket.onopen = function(evt) { onOpen(evt) }; websocket.onclose = function(evt) { onClose(evt) }; websocket.onmessage = function(evt) { onMessage(evt) }; websocket.onerror = function(evt) { onError(evt) }; } function onOpen(evt) { writeToScreen("CONNECTED"); doSend("WebSocket rocks"); } function onClose(evt) { writeToScreen("DISCONNECTED"); } function onMessage(evt) { writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data+'</span>'); websocket.close(); } function onError(evt) { writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data); } function doSend(message) { writeToScreen("SENT: " + message); websocket.send(message); } function writeToScreen(message) { var pre = document.createElement("p"); pre.style.wordWrap = "break-word"; pre.innerHTML = message; output.appendChild(pre); } window.addEventListener("load", init, false); </script> <h2>WebSocket Test</h2> <div id="output"></div>
これをコピペしたら今度は1行になるようなことはなかったです。
そして、これをローカルで表示させたらこうなりました。
で、ごにょごにょっとしたことを考えているので、自分の理解の範囲で動作を解釈してみます。(間違ってたら指摘いただけると幸いです)
- 動作は8行目から始まって、testWebSocket()が呼ばれる。
- 13行目のnewでwebsocketのインスタンスを生成。ここでソケットをオープンする。
- 14〜17行目はイベントハンドラ。ソケットをオープンすると、この中の14行目のonopenに設定したハンドラが呼ばれる。(先の13行目から呼ばれるところが変な感じがしますが、Javascriptのスコープの特性から14行目で定義している内容を13行目で使用可能なのですね)
- 20行目がonopenのイベントハンドラ。この中で、doSend()を呼んでその先でwebsocket.send()でデータを送信している。
- websocket.send()の結果、サーバ側からエコーバックが帰ってくる。
- エコーバックを受信すると、16行目で定義しているonmessageのハンドラが呼ばれるので、29行目のonMessage()が実行される。この中で、websocket.close()を呼んでコネクションをクローズ。
- クローズすると、15行目で定義しているoncloseに対応したハンドラが呼ばれる。
比較的簡単に使えそうですね。
ちょっとだけソケットの使い回しができることを確認してみました。
ソースコードをちょっとだけ弄ります。
<!DOCTYPE html> <meta charset="utf-8" /> <title>WebSocket Test</title> <script language="javascript" type="text/javascript"> var wsUri = "ws://echo.websocket.org/"; var output; var n = 10; function init() { output = document.getElementById("output"); testWebSocket(); } function testWebSocket() { websocket = new WebSocket(wsUri); websocket.onopen = function(evt) { onOpen(evt) }; websocket.onclose = function(evt) { onClose(evt) }; websocket.onmessage = function(evt) { onMessage(evt) }; websocket.onerror = function(evt) { onError(evt) }; } function onOpen(evt) { writeToScreen("CONNECTED"); doSend("WebSocket rocks START"); } function onClose(evt) { writeToScreen("DISCONNECTED"); } function onMessage(evt) { writeToScreen('<span style="color: blue;">RESPONSE: ' + evt.data+'</span>'); if( n > 0 ){ doSend("WebSocket rocks " + n); n--; } else { websocket.close(); } } function onError(evt) { writeToScreen('<span style="color: red;">ERROR:</span> ' + evt.data); } function doSend(message) { writeToScreen("SENT: " + message); websocket.send(message); } function writeToScreen(message) { var pre = document.createElement("p"); pre.style.wordWrap = "break-word"; pre.innerHTML = message; output.appendChild(pre); } window.addEventListener("load", init, false); </script> <h2>WebSocket Test</h2> <div id="output"></div>
変数nに初期値10を設定して、受信時の動作をnの値によって切り替えています。nが0より大きい場合には次のメッセージを送ってnをカウントダウン、nがゼロならソケットをクローズします。
結果は、
となりました。同じソケットを開いたまま11回のメッセージやりとりができていることがわかります。