WebSocket はじめのいっぽ

 WebSocketはサーバー/クライアント間での効率的な双方向通信を実現するための仕組みです。チャット・グループウェア・ゲームなどで利用されることが多いです。サーバー側はWebSocketに対応しているnode.jsなどを利用します。

WebSocketの動作とクライアント側の実装

 WebSocketによる通信では、まずサーバーとのコネクションを確立を行います。クライアント側からサーバー側へHTTPでコネクション確立のリクエストを送り、サーバー側が接続元やプロトコルを確認した後、接続可否のレスポンスを返します。接続が許可された場合、クライアント側はWebSocketによるコネクションを開始します。これをハンドシェイクと呼びます。クライアント側のハンドシェイクは以下の一行で済みます。

//  Insatiate WebSocket Object
var websocket = new WebSocket('ws://hoge.com/foo', 'protocol');

 コネクションが確立するとonopenイベントハンドラ、切断されるとoncloseイベントハンドラが実行されます。またメッセージをサーバーに送信するにはsendメソッド、受信するにはmessageイベントを捕捉します。クライアント側からコネクションを切断する処理を書くことはあまりないかもしれませんが、そのときにはcloseメソッドを利用します。

 コネクションの状況はWebSocketインスタンスのreadyStateプロパティを参照するとわかるようになっています。コネクションの状況を表す定数はそれぞれ、 WebSocket.CONNECTING = 0, WebSocket.OPEN = 1, WebSocket.CLOSING =2, WebSocket.CLOSED = 3というように定義されています。

// Insatiate WebSocket Object
var websocket = new WebSocket('ws://hoge.com/foo', 'protocol');

// On Open 
websocket.onopen = function(event) { ... }

// On Close
websocket.onclose = function(event) { ... } 

// Send Message From Client
websocket.send('THIS IS MESSAGE FROM CLIENT');

// On Message
websocket.onmessage = function(event) { 
  var receivedMessage = event.data;

  /*  処 理  */

}

// ------------------------------
//    JSONのやりとり
// ------------------------------
websocket.send(JSON.stringify({key1: value1, key2: value2});
websocket.onmessage = function(event) {
  var receivedMessage = JSON.parse(event.data);

/*   処 理  */

}

// ------------------------------
//    Binaryのやりとり
// ------------------------------
websocket.send(blob);
websocket.send(arrayBuffer);

websocket.binaryType = '[FORMAT]';
websocket.onmessage = function(event) {
  var receivedMessage = event.data;
  if ( receivedMessage == [Format] ) {

    /* 処 理 */

  }
}

WebSocketインスタンスのプロパティ

  • URL
  • readyState -> CONNECTING, OPEN, CLOSING or CLOSE
  • protocol
  • bufferAmount -> send()によって送信キューに貯まっている未送信バッファのサイズ
  • binaryType -> binaryフォーマット指定。blob or arraybuffer。
  • [event handler] onopen
  • [event handler] onerror
  • [event handler] onclose
  • [event handler] onmessage
  • [method] send(message)
  • [method] close()

アプリケーションの実装(サーバーサイド)

  • 【参考】node.jsのいろいろなモジュール23 – wsでWebSocket接続
  • 【参考】express – node Webフレームワーク

メッセージをクライアント側からサーバーに送り、それをサーバー側の画面に出力するだけの基本的なアプリケーションを作ってみました。まずwsをインストールします。

% mkdir workingdir
% cd workingdir
% npm install ws

続いてサーバー側の実装。1行目、2行目はwsモジュールを利用し、WebSocketServerインスタンスを生成。 WebSocketServerに対してconnectionがあったときには、

var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({port: [port number]});

wss.on('connection', function(ws){
  ws.on('message', function(message){
    console.log('received: %s', message);
  });
});

 ws API Documentに書いてあるとおりnew ws.Server([Options], [callback])はWebSocket severのインスタンスを生成します。引数の詳細は以下のとおり。portかserverのどちらかは必須です。

  • Options Object
    • host String
    • port Number
    • server http.Server
    • verifyClient Function
    • path String
    • noServer Boolean
    • disabelHixie Boolean
    • clientTracking Boolean
  • callback Function

アプリケーションの実装(クライアントサイド)

Chromeのコンソールで接続する場合は次のとおり

// コネクションを確立
var ws = new WebSocket('ws://localhost:[port number]');

// サーバーにメッセージを送信
ws.send("message");

Node.jsのREPLから接続する場合は次のとおり

// Instiate WebSocket Object
var WebSocket = require('ws');

var ws = new WebSocket('ws://localhost:[port number]');
ws.send("message");

サーバーサイドからのブロードキャスト

接続中のすべてのクライアントに受信したメッセージをブロードキャストするためには、サーバーサイドのコードを以下のように書き換えれば良い。

var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({port: 1025});

wss.broadcast = function(data) {
  for(var i in this.clients) {
    this.clients[i].send(data);
  }
};

wss.on('connection', function(ws){
  ws.on('message', function(message){
    console.log("received: %s", message);
    wss.broadcast(message);
  });
});

 これであるクライアントからのメッセージがサーバーで受信されると、全てのクライアントにブロードキャストするという動作をするようになります。次にブロードキャストしたデータをクライアント側できちんと受け取る処理を書きます。これはonmessageイベントをハンドルしてやればOKです。

var WebSocket = require('ws');
var ws = new WebSocket('ws://localhost:[port number]/');

ws.onmessage = function(event) {
  console.log(event.data);
}

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です