スマホですーっと線を引くと、PC側でもほぼリアルタイムにすーっと線が引かれる、
まさに「平成教育委員会」的なお絵かき・回答システム、作りたくないですか?
前回紹介したのがこちらです。
今回、その導入編になります!
前提条件・方針
- さくらVPSサーバー
(東京・CPU2コア・メモリ1GB・SSD)
- OS: CentOS 6
- Webサーバソフト:Nginx+Node.js の連携を実現する
※すでに他のWebページを、Nginxを使ってPHPのサイトを運営しているため、
今回ベースはNginxを使ってHTMLを提供し、Socket.IOでのやりとりのみNode.jsを通す、というやり方を模索しました。
つまり、Webページ(HTML)は、そのままNginxを使ってクライアントに提供しますが、
クライアントがサーバとSocket.IOによる双方向通信をしたいよ!という時だけ、Nginxへ一旦要求をもらって、Node.jsへ転送し、クライアント↔サーバ間をコネクションさせます。
難しいことを書きましたが、案外簡単にいけました!
① Node.jsとnpmのインストール
Node.jsをインストールします。
sudo yum install nodejs
次に、npm(Node.jsのパッケージ管理)をインストール。
これがあれば、Socket.IOなどのライブラリを入れることができます。
sudo yum install npm
そして、Socket.IOをインストールします。
# 任意のSocket.IOを動かすディレクトリを作成 sudo mkdir /var/sample # そこへ移動 cd /var/sample # npmを初期化 sudo npm init -y # Socket.IOをインストール sudo npm install socket.io
② NginxとNode.js(Socket.IO)との連携
Nginx未導入であれば、インストールします。
sudo yum install nginx
Nginxの設定ファイルを書き換えます。
設定ファイルは、一般的に、/etc/nginx/conf.d/default.confを書き換えればOKでしょう。
僕は、以下の形に書き換えました。
# default.conf #ここがポイント!Socket.IO通信時、ポート3000番にひねる upstream io_nodes { ip_hash; server 127.0.0.1:3000; } server { listen 80 default_server; listen [::]:80 default_server; server_name _; #root /usr/share/nginx/html; # Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; location / { root /var/www/html; index index.php index.html; } #PHPとの連携設定(PHP未使用なら不要) location ~ \.php$ { root /var/www/html; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param PATH_INFO $fastcgi_path_info; include fastcgi_params; } location ~ \.inc$ { deny all; } #ここがポイント! location /socket.io/ { proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_http_version 1.1; proxy_pass http://io_nodes; } error_page 404 /404.html; location = /40x.html { } error_page 500 502 503 504 /50x.html; location = /50x.html { } }
保存したら、Nginxを再起動します。
sudo service nginx restart
③ 双方向通信の動作確認
では、動作確認として、試しにページ更新不要な、リアルタイムチャットシステムを作ってみましょうか。
任意の作業ディレクトリ(今回:/var/sample配下)に、
チャットシステムを司る、javascriptのサーバプログラムを以下のように作ります。
「server.js」としました。
//server.js // 1.モジュールオブジェクトの初期化
//ポート3000番をリッスン var fs = require("fs"); var server = require("http").createServer(function(req, res) { res.writeHead(200, {"Content-Type":"text/html"}); var output = fs.readFileSync("./index.html", "utf-8"); res.end(output); }).listen(3000); var io = require("socket.io").listen(server); // 2.イベントの定義 io.sockets.on("connection", function (socket) { socket.on("msg", function (data) { console.log(data); io.sockets.emit("public", data); }); // 接続開始カスタムイベント socket.on("connected", function () { }); // メッセージ送信カスタムイベント socket.on("publish", function (data) { io.sockets.emit("publish", data); });
そして、チャットのWebページを作ります。
(これは、もちろん、Web公開ディレクトリにです)
「chat.html」
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999" xml:lang="ja" lang="ja"> <head> <title>Chat Test</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <script src="//code.jquery.com/jquery-1.11.0.min.js" type="text/javascript"></script> <script src="/socket.io/socket.io.js" type="text/javascript"></script> <script type="text/javascript"> var socket = io(); socket.on("connected", function () {}); // 接続時 socket.on("disconnect", function (client) {}); // 切断時 socket.on('public', function(msg) { console.log(msg); $("div[id=chat]").append("<div class='messages'>" + msg + "</div>"); }); $(document).ready(function(){ }); function sendMsg(){ var msg = $("input[name=msg]").val(); console.log(msg); socket.emit("msg", msg); } </script> </head> <body> <input type="text" name="msg" size="50" /> <input type="button" value="送信" onclick="sendMsg();" /><br><br> <div id="chat"></div> </body> </html>
このHTMLでは、以下のように、Socket.IOのライブラリを読み込んでいるのですが、
<script src="/socket.io/socket.io.js" type="text/javascript"></script>
さきほど、②でNginx↔Node.jsで連携を図れるようにした際、
Nginx側で「/socket.io/」へアクセス要求された時にポート3000番にひねる設定をしましたね。
さらに、Node.jsのプログラム(server.js)は、ポート3000番をリッスンしているため、server.jsへ飛んで、Socket.IOで通信ができるという仕掛けなのです!
最後に、server.jsを起動したら、リアルタイムチャットが動き出すはずです。
# server.jsを起動 node server.js
どうでしょうか?
ページを更新しなくても、2つのクライアント間で入力した文字が、リアルタイムに画面に反映されます!
では、次回はお絵かきのシステムを大公開しちゃいます。