リアルタイムなデータ通信はインタラクティブなwebコンテンツには不可欠の要素です。今回はリアルタイムなデータ通信を簡単にしてくれるSocket.IOを使ってパソコンとスマホがペアリングするコンテンツを作りました。Socket.IOの簡単な解説と共に紹介します。まずは次のデモをご覧ください。

※ ファイアーウォールの設定によっては閲覧できない可能性があります。デモ動画も御覧ください。

※ 全ソースコードをダウンロードし展開後のフォルダにてコマンドラインでnode serverを実行後、http://localhost:5000にアクセスするとローカル環境でもデモを確認できます。

デモについて

デモページにアクセスするとURLとペアリングコードが表示されます。以下、この画面をメイン画面と呼びます。指定のURLにスマホブラウザ等の別クライアント(ブラウザの別タブ、他の端末のブラウザ等。以下、コントローラと呼びます)でアクセスしてペアリングコードを入力するとその2つのクライアントが連携します。フリックするとメイン画面でパーティクルが発生します。また、1つのペアリングコードを使って複数のメイン画面をコントロールすることも可能です。

リアルタイムWebの実現とSocket.IO

web上においてリアルタイムの通信を実現するには、WebSocketCometといった技術があり、ブラウザによってその実装状況やAPIも様々です。Socket.IOはこれらのさまざまな実装の差異を吸収し統一されたAPIで使えるようにしたNode.jsの技術です。Node.jsとSocket.IOで構築されたwebサーバーにクライアントがwebブラウザを使ってアクセスすると、サーバーとリアルタイムにデータを送受信できるようになります。開発者はブラウザ間の実装の差異を意識することなくリアルタイムな通信処理を実現できます。

socket_sample1644

Node.jsとhttpサーバー、Socket.IOの準備

ここからはSocket.IOの簡単な使い方について説明していきます。まず、Socket.IOを使用するにはNode.jsが必要なので公式サイトよりインストーラーをダウンロードし手順にしたがってインストールしてください。インストール後、コマンドラインにてnode -vと実行し、Nodeのバージョンが表示されていればインストール成功です。

Node.jsインストール画面

つづいて、Node.jsが動作するhttpサーバーを準備します。もしお手元にNode.jsのhttpサーバーが存在しない場合は下記のファイルを使用ください。Node.jsのhttpモジュールfsモジュールを使ったシンプルなhttpサーバーです。Node.jsの処理はserver.jsファイルに記述してあります。

上記をダウンロードして展開しコマンドラインでそのフォルダに移動してnode(サーバーサイドのJavaScriptのスクリプト名)を実行するとhttp://localhost:5000にてローカルサーバーが起動します。今回のデモはserver.jsファイルがサーバーサイドのスクリプト名なので、node serverと実行します。Socket.IOはもちろん、Node.jsを試してみたい場合はこのserver.jsファイルに処理を追記すると便利です。

※ ファイアーウォールの設定によっては5000ポートでは起動できない場合があります。
※ 今回はサーバーサイドのJavaScriptとクライアントのファイルを全てルート直下に配置します。

【コマンドライン】

// Windowsでの移動
cd C:¥Users¥MyName¥sample_server
// macOSでの移動
cd /Users/MyName/sample_server
// httpサーバーの起動
node server

Socket.IOは以下のコマンドでインストールできます。今回使用したSocket.IOのバージョンは執筆時点(2014/12/22)の最新バージョンである1.2.1です。

【コマンドライン】

// Socket.IOのインストールコマンド
npm install socket.io

Socket.IOの使い方

サーバー側での処理

Node.jsで立てられたhttpサーバーがserverオブジェクトに格納されているとします。このhttpサーバーでSoclet.IOを使うには以下のようにします。

【サーバー側のJavaScript】

// socket.ioの読み込み
var socketIO = require("socket.io");
// サーバーでSocket.IOを使える状態にする
var io = socketIO.listen(server);

このNode.jsが動いているサーバーにクライアントのアクセスがあった場合、io.socketsconnectionイベントが発生します。この時発行されるsocketオブジェクトを使ってクライアントとのデータのやりとりをします。コードの例として、dataName1という名前で{ hoge : 1 }というデータをクライアントに送信し、dataName2という名前の{ fuga : "piyo" }というデータをクライアントから受信するコードを紹介します。

【サーバー側のJavaScript】

// サーバーへのアクセスを監視。アクセスがあったらコールバックが実行
io.sockets.on("connection", function (socket) {
    var dataToClient = {hoge : 1 };   // クライアントに送信するデータ例
    // 接続元のクライアントだけにデータ送信。
    socket.emit("dataName1", dataToClient);
    // 接続元のクライアント以外にデータ送信
    socket.broadcast.emit("dataName1", dataToClient);

    // クライアントからのデータの受信
    socket.on("dataName2", function(dataFromClient) {
        // 「piyo」という文字列がターミナルに出力される。
        console.log(dataFromClient.fuga);
    });
});

クライアント側でSocket.IOを使う

まず、クライアント側からSocket.IOを扱う為のJavaScriptであるsocket.io.jsファイルを読み込みます。socket.io.jsはサーバー側でsocketIO.listen(server)(上記参照)を実行すると自動的に用意されるJavaScriptで、(サーバーのURL)/socket.io/socket.io.jsの場所に用意されます。

【HTMLコード】

<script src="/socket.io/socket.io.js"></script>
<script src="/js/main.js"></script>

Socket.IOを使ってサーバーと接続するにはio.connect()メソッドを使います。ここで生成されるsocketオブジェクトを使ってサーバー側とデータをやりとりしますdataName2という名前で{ fuga : "piyo" }というデータをサーバーに送信し、dataName1という名前の{ hoge : 1 }というデータをサーバーから受信するコードの例を紹介します。サーバー側のAPIと見比べるとわかるように、サーバー側とクライアント側のAPIは共通しており扱いやすいものとなっています。

【クライアント側のJavaScript main.js】

// サーバーに接続
var socket = io.connect(location.origin);
// サーバーへデータを送信
socket.emit("dataName2", { fuga : "piyo" });
// サーバーからのデータを受信
socket.on("dataName1", function(dataFromServer) {
    // 「1」という数値がブラウザのコンソールに出力される。
    console.log(dataFromServer.hoge);
});

上記コードのデモ

説明したコードを記述した簡単なSocket.IOのデモを準備しました。上記ファイルをダウンロードして展開したファルダに移動して、コマンドラインでnode serverを実行してみてください。ブラウザのコンソールに1、コマンドラインにfugaが表示されていることが確認できます。

ペアリングを行う

今回のデモでは、メイン画面側はクライアントAがアクセスしてきた際にランダムなコードを発行します。コントローラでそのコードを入力するとクライアントAとクライアントBがサーバー側で同じグループに分けられます。その同じグループ間でのみデータを送受信することで、ペアリングを実現しています。Socket.IOには、アクセス中のクライアントをグループ化し通信処理を分けるroom機能があります。

room機能説明

socket.join("ルームID")を実行することでそのクライアントは指定されたグループ(ルームと呼ぶ)に所属している状態になります。クライアントからサーバーへデータを送信する際、送信先のグループを指定することで任意のグループにのみデータを送信することができます。

【サーバー側クライアント側共通のJavaScript記述】

var data = { hoge : 1 }; // 送信データ例
// roomIDのグループ(ルーム)に入れる
socket.join("roomID");
// roomIDにデータを送信する
socket.to("roomID").emit("someData", data);

PaaS「Heroku」を使ってリモートサーバー公開

Node.jsのコンテンツをリモートサーバーで確認するにはそのコンテンツを実行するための環境が必要です。自前で準備するのは大変なので、その実行環境を提供してくれるサービスPaaS(Platform as a Service)を使うと便利です。今回はSalesforceのHerokuを使いました。Herokuの使い方やPaaSの説明は下記をご参照ください。公式ドキュメントにてHerokuでの公開手順がわかりやすく説明されています。

最後に

今回のSocket.IOを使ったサーバーとクライアント間のリアルタイムなデータ通信を使うとフロントエンドだけでは実現できない表現が可能になります。サーバーサイドにNode.jsを使用することでフロントエンドエンジニアにとっては使い慣れたJavaScriptで1つのコンテンツ制作を完結させられます。是非お試しください。