Socket.IOを使ってNode.jsでリアルタイムWebアプリを開発する

2013年3月27日(水)
西谷 圭介

サーバ側実装

今回は例としてフォームに任意のメッセージを入力して送信すると接続中のクライアント全部に対してブロードキャストされる、非常にシンプルなチャットアプリケーションのようなものを作成します。

まず、eXcaleで利用可能にするために自動生成されたapp.jsをindex.jsという名前にリネームします。この辺りは前回、前々回の記事を参考にしてください。

続いてリネームしたindex.jsを修正していきます。expressコマンドで作成された状態からサーバを作成してListenする処理に関する記述を削除した上で以下の内容を追記します。

(省略)

//以下の2行をコメント化もしくは削除してください
//http.createServer(app).listen(app.get('port'), function(){
//  console.log("Express server listening on port " + app.get('port'));
//});

server = http.createServer(app);
var socketio = require('socket.io');
var io = socketio.listen(server);

server.listen(app.get('port'), function(){
  console.log("server listening on port " + app.get('port'));
});

io.sockets.on('connection', function (socket) { 
  var address = socket.handshake.address;
  console.log("connected from " + address.address + ":" + address.port);
  
  socket.on('msg', function(data){
    console.log(data);
    var now = new Date();
    var year = now.getFullYear();
    var month = ("0" + (now.getMonth() + 1)).slice(-2);
    var day = ("0" + now.getDate()).slice(-2);
    var hour = ("0" + now.getHours()).slice(-2);
    var minute = ("0" + now.getMinutes()).slice(-2);
    var second = ("0" + now.getSeconds()).slice(-2);
    var date = year + "-" + month + "-" + day + " " + hour + ":" + minute + ":" + second;
    var message = data.message;
 
    io.sockets.emit("msg", {date : date, message : message});
  });
  
  socket.on('disconnect', function () {
    console.log("disconnectted from " + address.address + ":" + address.port) 
  });
  
});

上から順を追って大まかに解説します。まず、サーバのListenをする上で今回はexpressのサーバを渡しています。なお、今まではソケット通信のためにhttpのサーバインスタンスかexpressのサーバが必要でしたが現在はスタンドアロンでも可能になりました。その場合、該当箇所は以下のようになります。

var io = require('socket.io').listen(8080);

また、待ち受けるポートについてですが、これはeXcaleで利用するためには8080番にする必要がありますので、expressで生成されたコードを変更しておいてください(詳細は前回記事を参考)。

コネクション接続・切断処理

まずはコネクション接続と切断のための処理を用意します。コネクション接続時のイベントを受け取れるようにした上で、コネクション接続時の処理を記述していきます。

今回の場合はio.sockets.on('connection', function (socket) { }でイベントを受け取り、接続時の処理としてログへの出力ならびにメッセージの送受信とコネクション切断時の処理を用意しています。コネクション切断時の処理も同様にコネクション切断のイベントを受け取った上でログの出力処理を行っています。

メッセージ受信処理

メッセージの受信は基本的にsocketオブジェクトのonというメソッドで行います。引数としてイベント名と実際に受信したメッセージ内容を取り、受信時の処理を関数内に記述していきます。

サンプルでは"msg"という名前のイベントを受信したら、ログへの出力および表示用の時刻を設定した上で受け取ったメッセージ内容を全クライアントへとブロードキャストしています。ブロードキャストに関しては次項で解説します。なお、イベント名は送信側、受信側で一致している必要があります。

socket.on( "eventname", function( data ){
});

メッセージ送信処理

メッセージ送信はemitというメソッドでイベントを発行することで行います。イベントの送り先は自分/自分以外の全て/自分を含む全てです。それぞれ以下のようになります。

// 自分自身へ送信
socket.emit("eventname", data);
// 自分以外の全てに送信
socket.broadcast.emit("eventname", data);
// 自分を含む全てに送信
io.sockets.emit("eventname", data);

今回は自分を含む全てに対して送信を行っているのでio.sockets.emitを使っています。なお、今回は使っていませんが送信に失敗した際に再送せずに破棄してしまう場合、つまり1度きりの送信を行う場合はvolatileというフラグをつけてemitを使います。

TIS株式会社

TIS株式会社所属。金融系基幹システムの開発等に従事したのち、サービス企画・開発を担当。IaaS開発を経て、現在はアプリ開発者のためのPaaS「eXcale」の開発責任者兼プログラマとして活動中。
Twitter:@Keisuke69
eXcale:http://www.excale.net/

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています