今回は、WebSocket APIについて解説と、WebSocketを使ったチャットアプリケーションのクライアント側の実装を行ないます。
WebSocketオブジェクト
ブラウザのJavaScriptからWebSocketを利用するために、WebSocket APIがW3Cで策定中です。執筆時点のブラウザ(Safari及びChrome)は、最新のドラフト「Editor's Draft 27 July 2010」に対応していません。ここでは、現行のブラウザが対応しているWebSocketの仕様を解説した後、最新の仕様について説明します。
インスタンス化
WebSocketはインスタンス時、第一引数に「ws://」または「wss://」で始まる文字列で接続先を指定します。また、省略可能な第二引数にはサブプロトコルを指定できます。サブプロトコルについては後述します。
イベント登録
WebSocketは以下の4つのイベントハンドラが定義されています。
onopen | WebSocketの接続が完了した時に呼ばれます(イベントタイプ:"open") |
onclose | WebSocketが切断された時に呼ばれます(イベントタイプ:"close") |
onmessage | 接続先からメッセージを受け取った時に呼ばれます(イベントタイプ:"message") |
onerror | エラー発生した時に呼ばれます(イベントタイプ:"error") |
メソッド
定義されているWebSocketのメソッドは以下の2つです。
send(message) | messageを接続先に送信します |
close() | WebSocketの接続を切断します。意図的に切断する時だけでなく、ウィンドウを閉じるとき、画面を遷移する時にも切断処理を行なう必要があります |
ステータス
WebSocketの接続状態を調べる事ができます。値こそ違いますが、XHR[1]のreadyStateプロパティと同様のものです。
readyState | 接続のステータスです。0~2の値をとります。読み取り専用です |
WebSocketクラスに定数が準備されています。ステータスを確認する際には必ず定数を使うようにしてください。
CONNECTING | 接続開始の処理中を示す定数です(= 0) |
OPEN | 接続済を示す定数です(= 1) |
CLOSED | 切断済を表す定数です(= 2) |
その他のプロパティ
その他に以下のプロパティがあります。
URL | 接続先を示すプロパティです。読み取り専用です |
bufferedAmount | sendメソッドによって送信が指定されてデータは、実際に送信されるまで待ち行列に追加されます。bufferedAmountは待ち行列のバイト数を返します。読み取り専用です |
サブプロトコル
サブプロトコルは、開発者がWebSocketプロトコル上で新しいプロトコルを定義する際に使用します。例えば、チャットとファイル転送でWebSocketを使い分けたい時等が考えられます。
Jettyでは、「WebSocketServlet」インターフェイスの実装の「doWebSocketConnect」メソッドにサブプロトコル名が渡されます。受け取ったサブプロトコル名により、使用するWebSocketの実装を切り換えることが可能になります。
今の仕様では、複数のサブプロトコルを同時に使うことは想定されておらず、WebSocketのインスタンス変数を複数準備する必要があるようです。
最新ドラフト
最新のドラフトでは以下のように修正されています。
サブプロトコルの複数指定
コンストラクタがひとつ増えました。第二引数のprotocolsは文字列の配列です。複数のサブプロトコルを複数指定できます。WebSocketプロトコルの仕様にはまだ反映されていないようですが、WebSocket APIの仕様を読む限りでは、接続元が指定した複数のサブプロトコルから、接続先がどれかひとつを選択するようです。
ステータス
WebSocketの接続状態を示すreadStateの仕様が変更になりました。
readyState | 接続のステータスの範囲が0~3に変更されました。読み取り専用です |
定数に「CLOSING」が増えています。それに伴い「CLOSED」の値が変更になっています。ドラフトの版の違いによる不具合を避けるためにも、ステータスを確認する際には必ず定数を使うようにしてください。
CONNECTING | 接続開始の処理中を示す定数です(= 0) |
OPEN | 接続済を示す定数です(= 1) |
CLOSING | 切断中を表す定数です(= 2) |
CLOSED | 切断済を表す定数です(= 3) |
プロパティ
protocol | サブプロトコル名を返します。インスタンス化の際に、サーバが選択したサブプロトコルを取得するために準備されたと思われます。読み取り専用です |
url | 接続先を示すプロパティが小文字に変更になりました。読み取り専用です |
クライアント側の実装
それでは、クライアント側の実装を行ないます。まず、Mavenによって作成された「src/main/resources」内に、「html」という名前の新しいディレクトリを作成してください。そして、以下の3つのファイルを作成します。
index.html
チャットアプリケーションのHTMLファイルです。後述する「common.css」と「common.js」を読み込んでいます。チャットのメッセージを入力するテキストボックスに「message」というidを、メッセージ送信用のボタンに「send」というidを割り当てています。また、メッセージの表示箇所のidは「messages」となっています。
common.css
チャットアプリケーションの見た目を整えるスタイルシートです。最低限の指定しか行なっていないため、説明は割愛します。
common.js
今回の肝となるJavaScriptのコードです[2]。詳細はコメントを参照してください。
チャットサーバの起動
これでWebSocketを使ったチャットの実装は一通り完成しました。それでは、サーバを起動してみましょう。
サーバを起動する前に、コンパイルをする必要があります。プロジェクト・エクスプローラー内の「WebSocketChat」プロジェクトを右クリックしコンテキストメニューを表示し、「実行」→「Maven package」を選択するとコンパイルが始まります[3]。コンソールに「BUILD SUCCESSFUL」と表示されれば、コンパイルの完了です。
その後、プロジェクト・エクスプローラー内の「WebSocketChat.java」ファイルを右クリックし、「実行」→「Java アプリケーション」を選択し、サーバを起動してください。
コンソールに「Started SelectChannelConnector@0.0.0.0:8040」と表示されたら、WebSocketに対応したブラウザのウィンドウを複数開き、それぞれ「http://localhost:8040/」にアクセスしてください。テキストボックスにメッセージを入力し、「send」ボタンをクリックすると、すべてのウィンドウにメッセージが表示されます。
次回予告
次回は、チャットをアプリケーション化し、誰でも簡単に起動できるようにします。