Node.js+Socket.IO
じゃーチャットを作ってこー。公式が提供してるのがあるので
これ見ながらやってみる。
Socket.IOをインストール
/home/dalomo/node-chatってディレクトリ作って
$ npm init
ってすると色々聞かれるので
{ "name": "node-chat", "version": "1.0.0", "description": "", "main": "app.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "dalomo", "license": "ISC" }
こんな感じにした(よく分かってない)。そしたら
$ npm install socket.io $ npm install express
でインストール。expressの方も必要みたい。
expressを利用したHelloWorld
公式の流れがこうだからまずこれをやるでござる。フォルダ内に
$ vi app.js
で
var app = require('express')(); var http = require('http').createServer(app); app.get('/', (req, res) => { res.send('<h1>Hello world</h1>'); }); http.listen(4000, () => { console.log('listening on *:4000'); });
3000番は使用中なので4000番に変えてみた。
自分の場合、前述の環境があるので/etc/nginx/conf.d/reverse_proxy.confに
location /node-chat/ { proxy_pass http://127.0.0.1:4000;proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
を追記。
これじゃダメだったみたい。
また、デーモン化のために/etc/systemd/system下にnode-chat.serviceを作り
[Unit] Description=node-chat After=network.target [Service] Type=simple ExecStart=/usr/bin/node /home/dalomo/node-chat/app.js Restart=always WorkingDirectory=/home/dalomo/node-chat [Install] WantedBy=multi-user.target
と記載した。そんで
$ systemctl daemon-reload $ systemctl start node-chat $ systemctl status node-chat ● node-chat.service - node-chat Loaded: loaded (/etc/systemd/system/node-chat.service; disabled; vendor preset: disabled) Active: active (running) since Sat 2020-12-05 15:39:28 JST; 8s ago Main PID: 13123 (node) CGroup: /system.slice/node-chat.service mq13123 /usr/bin/node /home/dalomo/node-chat/app.js Dec 05 15:39:28 1scp2bi4 systemd[1]: Started node-chat. Dec 05 15:39:28 1scp2bi4 node[13123]: listening on *:4000
うむ。じゃあhttp://dalomo.net/node-chat/にアクセスしてみますと
あれ…?いかん、ここで躓くのはいかんぞ。
ここ見るとルートの設定が違うっぽい!app.jsを
app.get('/', (req, res) => { ↓ app.get('/node-chat/', (req, res) => {
に変えてrestartみると
できたー!あぶねー。
クライアント側HTMLを作成
app.jsの内容を
app.get('/node-chat/', (req, res) => { res.sendFile(__dirname + '/index.html'); });
こう変更。__dirnameっていうのはapp.jsのパスをとってきてくれる。こうするとレスポンスに作成したindex.htmlを返すよーってなる。で、HTMLは丸パクる(タイトルだけ変えた^^)。
<html> <head> <title>node-chat</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font: 13px Helvetica, Arial; } form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; } form input { border: 0; padding: 10px; width: 90%; margin-right: 0.5%; } form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; } #messages { list-style-type: none; margin: 0; padding: 0; } #messages li { padding: 5px 10px; } #messages li:nth-child(odd) { background: #eee; } </style> </head> <body> <ul id="messages"></ul> <form action=""> <input id="m" autocomplete="off" /><button>Send</button> </form> </body> </html>
そうすっと
こうなった。CSS全然わからないので、なんでこうなるのか分かんない。
Socket.IOの処理を実装
接続確認
これもめちゃめちゃコピペである。app.jsに
var io = require('socket.io')(http);
と
io.on('connection', (socket) => { console.log('a user connected'); });
を追記。index.htmlの</body>の前に
<script src="/socket.io/socket.io.js"></script> <script> var socket = io(); </script>
を追記。そんでアクセスしてみると、statusに出てこない。なんでや。
ブラウザ側の開発者ツールを開きconsoleを見てみると
Uncaught SyntaxError: Unexpected token '<' socket.io.js:1
との表記があり、socket.io.js:1 のURLを確認してみると
https://dalomo.net/socket.io/socket.io.js
に行こうとしているようだった。そこにー私はーいませんー。ていうことはindex.htmlの
<script src="/socket.io/socket.io.js"></script>
ここのsrcを明示してあげればいいのかなーと思ってnode_modules/socket.io-client/dist/socket.io.jsに変更した。でも今度は
net::ERR_ABORTED 404
となる。うむむー?
こちら試してみたりしたけどうまくいかず。試しに
の、package.jsonに記載の同バージョンのsocket.io.jsを指定してみると、エラーは消えた。でもlogにa user connectedって出てこない。なんでだろ。ただなんか開発者ツールでNetwork欄を見てみると
なんかやってそうではある…。わっかんないなー。とりあえず進めてみよう。
進めてみたけど失敗する
もろコピペでapp.jsに
io.on('connection', (socket) => { socket.on('chat message', (msg) => { io.emit('chat message', msg); }); });
と変更。index.htmlを
<script> $(function () { var socket = io(); $('form').submit(function(e){ e.preventDefault(); // prevents page reloading socket.emit('chat message', $('#m').val()); $('#m').val(''); return false; }); socket.on('chat message', function(msg){ $('#messages').append($('<li>').text(msg)); }); }); </script>
と変更してみて、試したけどメッセージは表示されなかった。なんだろなー。
上手くいった例
nginxとApacheを止めて、app.jsのポートを80番に変更。そんで
!http://サーバーのIPアドレス/node-chat
にアクセスすると上手くいった。複数タブを表示させて片方に入力し、もう片方で見るとちゃんとメッセージが表示されてる。つーことはnginxをかましてNode.jsアプリに振る所でなにかがおかしいんじゃないかなーと思う。
nginxを設定し直す
などを参考に
upstream websocket {
ip_hash;
server 127.0.0.1:4000;
}
server {
・・・
location /node-chat/ {
proxy_pass http://websocket;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
server {
・・・
location /node-chat/ {
proxy_pass http://websocket;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
あたりを変えてみた。けどやっぱつながらない。
Socket.IOのディレクトリを指定する
なんかを参考にapp.jsの
var io = require('socket.io')(http, {path: "/node-chat/socket.io"});
て変えて、index.htmlも
var socket = io.connect("/", {path: "/node-chat/socket.io"});
と変えてみた。そしたらー
できましたー!
もしかしたらディレクトリの指定だけでいけたんだったりして…。まぁ検証する気力が湧いてこないので、とりあえずここまで!よしっ!
コメント