Socket.IO開発時に役立つツール4選とroom、namespaceライブラリの使い方Socket.IOで始めるWebSocket超入門(終)(1/3 ページ)

本連載では、WebSocketを扱えるNode.jsのライブラリ「Socket.IO」の使い方について解説します。今回は、チャットアプリ開発を進めながら、「room」「namespace」ライブラリの使い方について説明し、最後に開発時に役立つツールを4つ紹介します。

» 2016年07月04日 05時00分 公開
[猪熊朔也三菱総研DCS]

 本連載「Socket.IOで始めるWebSocket超入門」では、WebSocketを扱うことができるNode.jsのライブラリ「Socket.IO」を使って、サンプルアプリケーションを構築していきます。

 具体的には、チャットを題材とし、送受信されるメッセージ内容が即時反映されるリアルタイムかつ双方向なWebアプリケーションの構築を目標とします。さらに構築の中で、Socket.IOの各種ライブラリの使い方について解説することで、Socket.IOを使ったWebSocketの実践方法を体系的に学びます。

 前回の「チャットアプリ開発に見る、Socket.IOの基本ライブラリの使い方」では、実際にチャットアプリ開発をしながら、Socket.IO基本ライブラリの使い方を確認しました。今回は、さらにチャットアプリ開発を進めながら、「room」「namespace」ライブラリの使い方について説明します。

 以降は、前回のチャットアプリ開発までが完了していることが前提です。もし、まだチャットアプリ開発まで終わっていない方は、前々回、前回記事を参考にしてみてください。

「room」「namespace」とは

 Socket.IOでは、データの送受信だけではなく、「room」「namespace」という2つのライブラリを提供しています。

 roomは、双方向・リアルタイムデータ送受信を任意の範囲で行うための仕組みです。roomを使用すると、文字通り、その部屋に所属するクライアント間のみでデータをやりとりすることが可能です。

 namespaceは、Socket.IOの実装を機能単位で分割するための仕組みです。例えば、現在のチャットアプリに外部API連携機能や、お知らせ機能を追加する際に、namespaceを使用すると簡単に実装することが可能です。

 それでは、2つのライブラリについて、順に実装しながら説明します。

roomを使ったチャットルームの実装

 前回記事時点でのチャットアプリには、チャットルームがありません。そこで、チャットルーム機能をroomを使用して実装します。今回は、「部屋01」「部屋02」という2つの部屋を用意します。実現したいことのイメージ図を以下に記載します。

チャットルーム機能イメージ図

 それでは、実際に実装してみましょう。

クライアント側の実装

 まずは、クライアントサイドです。

  1. <!DOCTYPE html>
  2. <html lang="ja">
  3. <head>
  4. <meta charset="utf-8">
  5. <title>websocket-chat</title>
  6. <link rel="stylesheet"
  7. href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
  8. <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
  9. <!-- C01. Socket.IOクライアントライブラリの読込み -->
  10. <script type="text/javascript" src="/socket.io/socket.io.js"></script>
  11. </head>
  12. <body>
  13. <div class="container">
  14. <h1>WebSocket-Chat</h1>
  15. <form class="form-inline">
  16. <div class="form-group">
  17. <label class="roomLabel" for="rooms">部屋:</label>
  18. <select class="form-control" id="rooms">
  19. <option value="room01">部屋01</option>
  20. <option value="room02">部屋02</option>
  21. </select>
  22. <label class="nameLabel" for="msgForm">名前:</label>
  23. <input type="text" class="form-control" id="msgForm">
  24. </div>
  25. <button type="submit" class="btn btn-primary" id="sendButton">入室</button>
  26. </form>
  27. <div id="chatLogs"></div>
  28. </div>
  29. <script type="text/javascript">
  30. var socket = io.connect(); // C02. ソケットへの接続
  31. var isEnter = false;
  32. var name = '';
  33. // C04. server_to_clientイベント・データを受信する
  34. socket.on("server_to_client", function(data){appendMsg(data.value)});
  35. function appendMsg(text) {
  36. $("#chatLogs").append("<div>" + text + "</div>");
  37. }
  38. $("form").submit(function(e) {
  39. var message = $("#msgForm").val();
  40. var selectRoom = $("#rooms").val();
  41. $("#msgForm").val('');
  42. if (isEnter) {
  43. message = "[" + name + "]: " + message;
  44. // C03. client_to_serverイベント・データを送信する
  45. socket.emit("client_to_server", {value : message});
  46. } else {
  47. name = message;
  48. var entryMessage = name + "さんが入室しました。";
  49. socket.emit("client_to_server_join", {value : selectRoom});
  50. // C05. client_to_server_broadcastイベント・データを送信する
  51. socket.emit("client_to_server_broadcast", {value : entryMessage});
  52. // C06. client_to_server_personalイベント・データを送信する
  53. socket.emit("client_to_server_personal", {value : name});
  54. changeLabel();
  55. }
  56. e.preventDefault();
  57. });
  58. function changeLabel() {
  59. $(".nameLabel").text("メッセージ:");
  60. $("#rooms").prop("disabled", true);
  61. $("button").text("送信");
  62. isEnter = true;
  63. }
  64. </script>
  65. </body>
  66. </html>
index.html(17~22、44、53、64~65行目が追加・変更部分)

 クライアントサイドでは、チャット部屋のセレクトボックスと、選択された部屋名をサーバサイドに送信するclient_to_server_joinイベントを追加しています。

サーバ側の実装

 続いてサーバサイドです。

  1. // S01. 必要なモジュールを読み込む
  2. var http = require('http');
  3. var socketio = require('socket.io');
  4. var fs = require('fs');
  5. // S02. HTTPサーバを生成する
  6. var server = http.createServer(function(req, res) {
  7. res.writeHead(200, {'Content-Type' : 'text/html'});
  8. res.end(fs.readFileSync(__dirname + '/index.html', 'utf-8'));
  9. }).listen(3000); // ポート競合の場合は値を変更
  10. // S03. HTTPサーバにソケットをひも付ける(WebSocket有効化)
  11. var io = socketio.listen(server);
  12. // S04. connectionイベントを受信する
  13. io.sockets.on('connection', function(socket) {
  14. var room = '';
  15. var name = '';
  16. // roomへの入室は、「socket.join(room名)」
  17. socket.on('client_to_server_join', function(data) {
  18. room = data.value;
  19. socket.join(room);
  20. });
  21. // S05. client_to_serverイベント・データを受信する
  22. socket.on('client_to_server', function(data) {
  23. // S06. server_to_clientイベント・データを送信する
  24. io.to(room).emit('server_to_client', {value : data.value});
  25. });
  26. // S07. client_to_server_broadcastイベント・データを受信し、送信元以外に送信する
  27. socket.on('client_to_server_broadcast', function(data) {
  28. socket.broadcast.to(room).emit('server_to_client', {value : data.value});
  29. });
  30. // S08. client_to_server_personalイベント・データを受信し、送信元のみに送信する
  31. socket.on('client_to_server_personal', function(data) {
  32. var id = socket.id;
  33. name = data.value;
  34. var personalMessage = "あなたは、" + name + "さんとして入室しました。"
  35. io.to(id).emit('server_to_client', {value : personalMessage});
  36. });
  37. // S09. dicconnectイベントを受信し、退出メッセージを送信する
  38. socket.on('disconnect', function() {
  39. if (name == '') {
  40. console.log("未入室のまま、どこかへ去っていきました。");
  41. } else {
  42. var endMessage = name + "さんが退出しました。"
  43. io.to(room).emit('server_to_client', {value : endMessage});
  44. }
  45. });
  46. });
app.js(16、19~23、27、31、46行目が追加・変更部分)

 サーバサイドでは、client_to_server_joinイベント受信処理を追加しています。アクセスしたクライアントを特定のroomに入室させるには、「socket.join(room名)」を使用します。

 また、emit(送信)処理を以下のように変更しています。

変更前 変更後
io.sockets.emit(全クライアント送信) io.to(room).emit
socket.broadcast.emit(ブロードキャスト送信) socket.broadcast.to(room).emit

 データ送信を特定のroomに限定するには、「to(room名)」を使用します。これにより、全クライアント送信・ブロードキャスト送信の範囲は指定したroomのみになります。

 ちなみに、入室したroomから退室したい場合は、「socket.leave(room名)」を使用します。ただし、Socket.IOでは、disconnectイベントが発生すると自動的にそのクライアントをroomから退出させます。入室したチャットルームを切り替えるなど、disconnectイベント以外でroom退室処理が必要な場合のみ使用すればいいでしょう。

動作確認

 コードの変更・保存が完了したら、アプリケーションの動作を確認します。4つのブラウザウィンドウでアプリケーションを開いてください。その後、部屋01、部屋02にそれぞれ2クライアントずつ入室します。

チャットルーム機能動作確認【1】

 部屋01、部屋02のクライアントでそれぞれメッセージを送信します。

チャットルーム機能動作確認【2】

 メッセージが、全クライアントではなく、部屋01、部屋02の範囲内でのみ共有されたことが確認できたと思います。このように、roomを使用すると、データの送信対象を任意にグループ化することができます。

roomへの入室:socket.join(room名) / roomから退室:socket.leave(room名)
       1|2|3 次のページへ

Copyright © ITmedia, Inc. All Rights Reserved.

スポンサーからのお知らせPR

HTML5�ス�ス陋幢ススX 鬮ォ�ェ陋滂ソス�ス�コ闕オ譁溷クキ�ケ譎「�ス�ウ驛「�ァ�ス�ュ驛「譎「�ス�ウ驛「�ァ�ス�ー

髫エ蟷「�ス�ャ髫エ魃会スス�・髫エ蟶キ�」�ッ闖ォ�」

注目のテーマ

4AI by @IT - AIを作り、動かし、守り、生かす
Microsoft & Windows最前線2025
AI for エンジニアリング
ローコード/ノーコード セントラル by @IT - ITエンジニアがビジネスの中心で活躍する組織へ
Cloud Native Central by @IT - スケーラブルな能力を組織に
システム開発ノウハウ 【発注ナビ】PR
あなたにおすすめの記事PR

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。