リアルタイムなデータ通信はインタラクティブなwebコンテンツには不可欠の要素です。今回はリアルタイムなデータ通信を簡単にしてくれるSocket.IOを使ってパソコンとスマホがペアリングするコンテンツを作りました。Socket.IOの簡単な解説と共に紹介します。まずは次のデモをご覧ください。
※ ファイアーウォールの設定によっては閲覧できない可能性があります。デモ動画も御覧ください。
※ 全ソースコードをダウンロードし展開後のフォルダーにてコマンドラインでnode server
を実行後、http://localhost:5000にアクセスするとローカル環境でもデモを確認できます。
デモについて
デモページにアクセスするとURLとペアリングコードが表示されます。以下、この画面をメイン画面と呼びます。指定のURLにスマホブラウザ等の別クライアント(ブラウザの別タブ、他の端末のブラウザ等。以下、コントローラーと呼びます)でアクセスしてペアリングコードを入力するとその2つのクライアントが連携します。フリックするとメイン画面でパーティクルが発生します。また、1つのペアリングコードを使って複数のメイン画面をコントロールすることも可能です。
リアルタイムWebの実現とSocket.IO
web上においてリアルタイムの通信を実現するには、WebSocketやCometといった技術があり、ブラウザによってその実装状況やAPIもさまざまです。Socket.IOはこれらのさまざまな実装の差異を吸収し統一されたAPIで使えるようにしたNode.jsの技術です。Node.jsとSocket.IOで構築されたwebサーバーにクライアントがwebブラウザを使ってアクセスすると、サーバーとリアルタイムにデータを送受信できるようになります。開発者はブラウザ間の実装の差異を意識することなくリアルタイムな通信処理を実現できます。
Node.jsとhttpサーバー、Socket.IOの準備
ここからはSocket.IOの簡単な使い方について説明します。まず、Socket.IOを使用するにはNode.jsが必要なので公式サイトよりインストーラーをダウンロードし手順にしたがってインストールしてください。インストール後、コマンドラインにてnode -v
と実行し、Nodeのバージョンが表示されていればインストール成功です。
つづいて、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のバージョンは記事メンテナンス時点(2018年6月現在)の最新バージョンである2.1.1です。
【コマンドライン】
// Socket.IOのインストールコマンド
npm install socket.io
Socket.IOの使い方
サーバー側での処理
Node.jsで立てられたhttpサーバーがserver
オブジェクトに格納されているとします。このhttpサーバーでSoclet.IOを使うには以下のようにします。
【サーバー側のJavaScript】
// socket.ioの読み込み
const socketIO = require("socket.io");
// サーバーでSocket.IOを使える状態にする
const io = socketIO.listen(server);
このNode.jsが動いているサーバーにクライアントのアクセスがあった場合、io.sockets
のconnection
イベントが発生します。この時発行されるsocket
オブジェクトを使ってクライアントとのデータのやりとりをします。コードの例として、dataName1
という名前で{ hoge : 1 }
というデータをクライアントに送信し、dataName2
という名前の{ fuga : "piyo" }
というデータをクライアントから受信するコードを紹介します。
【サーバー側のJavaScript】
// サーバーへのアクセスを監視。アクセスがあったらコールバックが実行
io.sockets.on("connection", socket => {
const 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】
// サーバーに接続
const socket = io.connect(location.origin);
// サーバーへデータを送信
socket.emit("dataName2", { fuga: "piyo" });
// サーバーからのデータを受信
socket.on("dataName1", dataFromServer => {
// 「1」という数値がブラウザのコンソールに出力される。
console.log(dataFromServer.hoge);
});
上記コードのデモ
説明したコードを記述した簡単なSocket.IOのデモを準備しました。上記ファイルをダウンロードして展開したファルダに移動して、コマンドラインでnode server
を実行してみてください。ブラウザのコンソールに1
、コマンドラインにfuga
が表示されていることが確認できます。
ペアリングを行う
今回のデモでは、メイン画面側はクライアントAがアクセスしてきた際にランダムなコードを発行します。コントローラーでそのコードを入力するとクライアントAとクライアントBがサーバー側で同じグループに分けられます。その同じグループ間でのみデータを送受信することで、ペアリングを実現しています。Socket.IOには、アクセス中のクライアントをグループ化し通信処理を分けるroom機能があります。
socket.join("ルームID")
を実行することでそのクライアントは指定されたグループ(ルームと呼ぶ)に所属している状態になります。クライアントからサーバーへデータを送信する際、送信先のグループを指定することで任意のグループにのみデータを送信できます。
【サーバー側クライアント側共通のJavaScript記述】
const 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つのコンテンツ制作を完結させられます。是非お試しください。