4. クライアント側のエンドポイントの実装
クライアント側については、今回はJavaScriptで実装することにした。W3Cが策定中の標準APIである「The WebSocket API」を使ったWebSocket通信は、接続先のURLを指定してWebSocketインターフェースのインスタンスを作成することから始まる。URLは「ws:」または「wss:」(httpsに相当するセキュア接続用)というURIスキームを持つ形式で表される。次の例は、上で作成したHelloEndpoint.javaに接続する例である。
WebSocket webSocket = new WebSocket('ws://localhost:9080/WebSocketSample/Hello');
このコンストラクタはインスタンスを作成すると同時に対象のURLに対してWebSocketプロトコルによる接続を試みる。作成したWebSocketインスタンスには、クライアントエンドポイントの4つのイベント(onpen、onmessage、onclose、onerror)に対応したハンドラをそれぞれ定義する。次のコードは、WebSocketの接続を開始し、4つのイベントハンドラを定義する例である。
var webSocket = null; function connect() { if (webSocket == null || webSocket.readyState != webSocket.CONNECTING || webSocket.readyState != webSocket.OPEN) { // WebSocketオブジェクトのインスタンス化 webSocket = new WebSocket('ws://localhost:9080/WebSocketSample/Hello'); // 各種イベントハンドラの定義 // 接続がオープンしたとき webSocket.onopen = function(event) { document.getElementById("status").innerHTML = "接続中"; }; // メッセージを受信したとき webSocket.onmessage = function(event) { var message = event.data; document.getElementById("message").innerHTML = "<strong>" + message + "</strong>"; }; // 接続がクローズしたとき webSocket.onclose = function(event) { document.getElementById("status").innerHTML = "切断中"; webSocket = null; }; // エラーが発生したとき webSocket.onerror = function(event) { alert("An error was occured."); document.getElementById("status").innerHTML = "切断中"; }; } }
この例では、接続の開始と切断、そしてエラー発生時に接続状態の表示を切り替えるようになっている。そしてメッセージを受信した場合には、その内容をページに表示する。現在の接続状態を知るにはWebSocketインスタンスのreadyState属性の値を調べればよい。WebSocketインターフェースには次の4つの状態が定義されている。
- CONNECTING:接続を開始しているが、まだ確立していない
- OPEN:接続が確立している
- CLOSING:接続のクローズを実行中
- CLOSED:接続がクローズされたか、または接続をまだ開始していない
つまりこの例では、まだ接続を開始していない場合にのみ接続を試みているというわけだ。サーバーにメッセージの送信したい場合には、接続状態にあるWebSocketインスタンスに対して次のようにsend()メソッドを実行すればよい。テキストを送信したい場合には、このメソッドに文字列を渡せばそれがサーバーに送信される。
function sendMessage() { if (webSocket.readyState == webSocket.OPEN) { webSocket.send("HELLO!"); } }
接続をクローズするには、次のようにclose()メソッドを実行する。
function disconnect() { if (webSocket.readyState == webSocket.OPEN) { webSocket.close(); } }
以上をまとめて、Helloエンドポイントと通信するクライアントのコードは次のように書くことができる。
<!DOCTYPE HTML> <html> <head> <title>WebSocketのサンプル</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script type="text/javascript"> var webSocket = null; // WebSocket接続 function connect() { if (webSocket == null || webSocket.readyState != webSocket.CONNECTING || webSocket.readyState != webSocket.OPEN) { // WebSocketオブジェクトのインスタンス化 webSocket = new WebSocket('ws://localhost:9080/WebSocketSample/Hello'); // 各種イベントハンドラの定義 // 接続がオープンしたとき webSocket.onopen = function(event) { document.getElementById("status").innerHTML = "接続中"; }; // メッセージを受信したとき webSocket.onmessage = function(event) { var message = event.data; document.getElementById("message").innerHTML = "<strong>" + message + "</strong>"; }; // 接続がクローズしたとき webSocket.onclose = function(event) { document.getElementById("status").innerHTML = "切断中"; webSocket = null; }; // エラーが発生したとき webSocket.onerror = function(event) { alert("An error was occured."); document.getElementById("status").innerHTML = "切断中"; }; } } // ソケットの切断 function disconnect() { if (webSocket.readyState == webSocket.OPEN) { webSocket.close(); } } // メッセージの送信 function sendMessage() { if (webSocket.readyState == webSocket.OPEN) { var text = document.getElementById('inputmessage').value; webSocket.send(text); document.getElementById('inputmessage').value = ""; } } </script> </head> <body> <h1>WebSocketのサンプル</h1> <div> <button type="submit" onclick="connect()">接続</button> <button type="submit" onclick="disconnect()">切断</button> <span id="status" style="font-style:italic;margin-left:100px;">切断中</span> </div> <div style="margin-top:20px;"> メッセージ入力:<input id="inputmessage" type="text" size="50" /> <button type="submit" onclick="sendMessage()">送信</button> </div> <p>受信メッセージ:</p> <div id="message" style="margin-left:20px;"></div> </body> </html>