Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

Express×socket.ioを使ってwebsocketで遊ぼう~第1話~

More than 3 years have passed since last update.
参考にしていただければ幸いですが、参考にして不具合等が起きた場合、保障はできませんのであしからず。
間違い等あればご教授いただけると助かります。

>> 追記(2017/07/20)
nodejs, npm のインスコ方法を記載しました。
(epelからyumインスコすると、バージョンv0.10が入るので・・・)

この回のゴール

・websocket通信をsocket.ioとExpressを使用して実装
・送信したデータの共有

環境

Windows7
Node.js v0.10.25
* 検証環境
Opera 32
Chrome 46
FireFox 41
IE 9(検証のためにダウングレードしてた・・・)

Node.jsのインスコ

windowsの場合は本家から落とすだけです。
コマンドプロンプト上で「node -v」と打って、バージョンが表示されればOK。
 されなければ、環境変数に追加してやってください。

CentOSの場合は下記コマンドを打ってください。
※CentOS6以外の場合は一行目のepelリポジトリの参照元を変えてください

$ rpm -ivh http://ftp.iij.ad.jp/pub/linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
$ curl --silent --location https://rpm.nodesource.com/setup_6.x | bash -
$ yum install -y gcc gcc-c++ nodejs

ベースプロジェクトの作成

 Express とは・・・
  Node.js用のフレームワーク

Expressのインスコ

sudo npm install -g express-generator

-g でグローバルにインストールします。

express コマンドが使用できればokです。

作業フォルダを作成

以下のような構成でフォルダを3つ用意します

フォルダ構成
socketTest
├━ socket
└━ chat

socketフォルダ:websocketのサーバーとします
chatフォルダ:実際にチャットを行うHTMLを設置します

socketサーバーを構築

Expressフレームワークを設置

shell
$ cd socketTest/socket
$ express # expressのテンプレ構築
$ npm install # 必要なパッケージのインスコ
$ npm install socket.io # package.jsonに記述してもOKです

socket.ioを扱うための準備

shell
$ mkdir routes/module
$ touch mod_socket.js

上のコマンドで作成した「mod_socket.js」というファイルにwebsocket起動用のスクリプトを書いていきます。

socketTest/socket/routes/module/mod_socket.js
var http = require('http');
//サーバインスタンス作成
var server = http.createServer(function (req, res) {
        res.writeHead(200, {'Content-Type':'text/html'});
        res.end('server connected');
});
var io = require('socket.io').listen(server);

  server.listen(8888);//8888番ポートで起動

  //接続確立時の処理
  io.sockets.on('connection', function (socket) {
    // この中でデータのやり取りを行う
    console.log('connected');
  });

app.js内で「mod_socket/js」というファイルを読み込むようにします。
上部のvar群の一番下に追加する形でいいかもですね。

socketTest/socket/app.js
// socket
var socket = require('./routes/module/mod_socket.js');

Nodeサーバーの起動

ここまで来たら、Expressが動作するか確認してみましょう。

Express自体はデフォルト3000番ポートになります。
websocket自体は指定したとおり8888番を用意しているので、下記のように確認してみます。

shell
$ pwd
***/socketTest/socket
$ npm start

npm start で起動
ctrl + c で終了です。たまに、終了に時間がかかります

Expressとsocket.ioの確認

http://localhost:3000
express.png
Expressの初期ページが表示されています。

http://localhost:8888/socket.io/socket.io.js
websocket通信用にsocket.ioで自動生成されるjsファイルです。

外部のHTMLからwebsocket通信

フォルダ構成
socketTest
├━ socket # wsサーバー
└━ chat # こっちを使います
socketTest/chat/index.html
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>チャットルーム</title>
    <!-- /* socket.ioのjsを読み込む */ -->
    <script type="text/javascript" src="http://localhost:8888/socket.io/socket.io.js"></script>
    <script type="text/javascript">
        var socket;
        (function(){
            // socket通信が開始される
            socket = io.connect("http://localhost:8888");
        })();
    </script>
</head>
<body>

</body>
</html>

成功すれば、シェルの方に「connected」というメッセージが出ていると思います。
(画像では4ブラウザで開いていたのでその分ログが出ています)

express-shell.png

これは、「socketTest/socket/routes/module/mod_socket.js」に記述したconsole.logの内容になります。
(一応JSなのでconsole.logでのデバッグが可能です)
外部からwebsocket通信に接続されると、mod_socket.jsファイルの connection を通過します。
この connection はsocket.ioのデフォルトで用意されているものになります。

外部のHTMLからメッセージを送る

@ポイント
・データの送信にはemit、受信にはonというファンクションを使用します。
・送受信するデータはJSON形式ですが、送信時はJSON.stringifyを使って文字列形式に変換
 受信時はJSON.parseを使ってJSON形式に変換してやり取りをする

socketTest/socket/routes/module/mod_socket.js(L:11)
  //接続確立時の処理
  io.sockets.on('connection', function (socket) {
    // この中でデータのやり取りを行う
    // 「message」という名前で受信したデータはこの中を通る
    socket.on('message', function(d){
      // そのまま全接続先へ送信
      io.emit('receiveMessage', d);
    });
  });
socketTest/chat/index.html[body内]
<body>
    <div>
        <textarea id="message" rows="4" cols="40"></textarea>
        <button type="button" id="send">Send</button>
    </div>
    <div>
        <ul id="messageList"></ul>
    </div>
</body>
socketTest/chat/index.html[2つ目のscript内]
    var socket, emit;
    (function(){
        socket = io.connect("http://localhost:8888");
        emit = function (name, data){
            // json → 文字列に変換して送信する関数
            socket.emit(name, JSON.stringify(data));
        }
    })();
    window.onload = function(){
        var sendBtn = document.getElementById('send');
        var message = document.getElementById('message');
        sendBtn.addEventListener("click", function(){
            emit('message', {text: message.value});
        });
        socket.on('receiveMessage', function(d){
            var data = JSON.parse(d), // 文字列→JSON
                li = document.createElement('li'), // liタグ作成
                list = document.getElementById('messageList'); // ulタグの取得
            li.textContent = data.text; // liタグに値を入れる
            list.appendChild(li); // ulタグの子ノードとして作成したliタグを追加
        });
    };

複数ブラウザで立ち上げて、メッセージを送信するとそれぞれの画面に送信したメッセージが
どんどん表示されていくと思います。

express-2.png

今回はひとまずここまでです。

iotlt
IoT縛りの勉強会です。 毎月イベントを実施しているので是非遊びに来てください! 登壇者を中心にQiitaでも情報発信していきます。 https://iotlt.connpass.com
https://iotlt.connpass.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away