RAKUS Developers Blog | ラクス エンジニアブログ

株式会社ラクスのエンジニアブログ

Node.js + Express + Socket.ioで遊んでみた

はじめに

id:d_shrです。
担当している商材の機能を実装する上でNode.js, Express, Socket.ioについて学習する機会があったのでまとめてみようと思います。 Socket.ioのサンプルコードを参考に簡単にチャットアプリの基本的な機能を作ってみました。
簡単にWebアプリケーションを作ってみたいという方やNode.jsやSocket.ioを学習し始めた方の参考になればと思います。

Node.js

Node.jsについては過去の記事で紹介されているので割愛します。
Node.jsの勉強会でお手軽にWebアプリを作った話 - RAKUS Developers Blog

知ってる?nodemailerを使ってメールを送る方法 - RAKUS Developers Blog

Express

ExpressはNode.js向けの軽量なフレームワークです。
ちょっとめんどくさい外部からの要求と内部ロジックをマッピングする基本的なルーティング機能が簡単にできたり、express-generatorによってアプリケーションの雛型が簡単に作れる便利なやつ。
詳しい説明や使い方は公式サイトに書かれています。

Socket.io

サーバとクライアント間の通信で非同期かつ双方向の通信を実現するためのプロトコルであるWebSocketを手軽に利用できるモジュールです。 Node.jsのnpmで提供されています。
詳しい説明や使い方は公式サイトに書かれています。

チャットを作ってみた

Node.js, Express, Socket.ioを利用して作ってみました。

実装した機能は2点です。
1. メッセージの送受信と表示
2. ログイン機能(Nodeサーバにリクエストがあるとログイン画面へ)

1. メッセージの送受信と表示

チャットの基本的な機能。
Socket.ioのGet startedをとりあえずやってみました。
チャットのサンプルコードでメッセージの送受信をどのように行うか説明されています。

クライアント側の処理
  • メッセージの表示や入力欄

f:id:d_shr:20180313144146p:plain

<!-- メッセージの表示 -->
<ul id="messages"></ul>

<!-- メッセージ入力欄 -->
<form action="#" id="chatForm">
  <input id="m" autocomplete="off" />
  <button>Send</button>
</form>

受信したメッセージを表示する部分と送信するメッセージの入力欄です。

  • メッセージ送信や受信メッセージの表示ロジック
<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
  var socket = io();
  var userName = '';
  $(function () {

    // メッセージを送信する
    $('form').submit(function(){
      socket.emit('chat message', $('#m').val());
      $('#m').val('');
      return false;
    });

    // 受信したメッセージを表示
    socket.on('chat message', function(data){
      var chat = data.userName + " : " + data.message;
      $('#messages').append($('<li>').text(chat));
    });
  });
</script>

通信を行うための基本的な操作は以下の2つです。
socket.emit('event', data);
イベントの発火、接続している全員(送信者含む)へdataを送信します。
socket.on('event', callback);
イベントの検知、送信されたdataを受信します。

ここでは、入力されたメッセージのSubmitをイベントchat messsageとしてサーバへメッセージが送られます。
イベントchat messsageを検知すると、サーバで処理され送信されてきたメッセージを受け取り表示します。

サーバ側の処理
  • サーバにアクセスすると実行される部分。
// モジュールを読み込む
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);

// Nodeサーバにアクセスがあるとindex.htmlへ遷移
app.get('/', function(req, res){
 res.sendFile(__dirname + '/index.html');
});

必要なモジュールをrequireで読み込み、index.html(クライアントの処理)へ遷移します。

  • メッセージの送信ロジック
// メッセージ送信処理
socket.on('chat message', function(msg){
  io.emit('chat message', msg);
});

クライアント側から送信されてきたメッセージをサーバで受け取り処理するところです。
接続しているクライアントへメッセージを送信します。
以上がチャットの基本的なメッセージのやりとりの処理になります。

2. Nodeサーバにリクエストがあるとログイン画面へ遷移

f:id:d_shr:20180313144150p:plain

理解を深めるために、データのやり取りをもう少し複雑にしてみようと思いつきで実装してみた機能。
実装したもの以下のとおりです。

  • ユーザ名を入力してログイン
  • ユーザ名を表示してメッセージを識別
  • データのやり取りにユーザの情報を追加
クライアント側の処理
  • ログインフォーム
<!-- ログインフォーム -->
<form id="loginForm">
  <div>
    <input id="username" name="username" type="text" class="form-control" placeholder="ユーザ名" autofocus />
    <button id="btnLogin">ログイン</button>
  </div>
</form>
  • ログイン処理
<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
  var socket = io();
  var userName = '';
  $(function () {
    // ログイン画面表示
    $('#loginForm').show();
    $('#chatForm').hide();

    // ログイン処理
    $('#btnLogin').on('click', function (e) {
      userName = $('#username').val();
      if (userName) {
        // チャット画面表示
        $('#loginForm').hide();
        $('#chatForm').show();
        // ユーザ情報をサーバへ通知する
        socket.emit('login', {
          userID: socket.id,
          userName: userName
        });
      }
      e.preventDefault();
    });
  });
</script>

主に追加したものはログイン時の処理です。
ログインフォームとチャットフォームの切り替え処理も入れたりしています。
socket.emit()で送信者のsocketのidと入力されたユーザ名を送信します。

サーバ側の処理
io.on('connection', function(socket){

  var loginUsers = []; //ログインユーザ

  // ログイン処理
  socket.on('login', function(userInfo){
    loginUsers[userInfo.userID] = userInfo.userName;
  });

  // メッセージ送信処理
  socket.on('chat message', function(msg){
    userName = loginUsers[socket.id];
    io.emit('chat message', {
      userName: userName,
      message: msg
    });
  });
});

ログイン時の処理とメッセージ送信時のデータを追加してみました。
ユーザの情報としてソケットIDをユーザID、クライアント側でログイン時に入力された値をユーザ名を持っています。 メッセージの送信時には、送信したユーザとそのメッセージを紐づけて、クライアント側へ送信します。
これでログイン機能、ユーザ名による識別を実現し、よりチャットっぽくなりました。

おわりに

学習したNode.js, Express, Socket.ioを使って実際にアウトプットしてみたことをまとめてみました。
環境構築と実装がすごく簡単ですぐにできます。
チャットについては、もう少し機能拡張したりコード自体をキレイにしたいと思います。

参考

Copyright © RAKUS Co., Ltd. All rights reserved.