Node.js初心者です。チャットを発展させたようなリアルタイムで情報のやりとりをするアプリを、見よう見まねで開発しています。
ローカルでテストをしているときは、順調に動いていたのですが、サーバーで運用すると、困った問題が発生しました。
スマホやパソコンがスリープになると、接続が切れてしまいます。
そこで、クライアントサイドで接続が切れたら、自動で再接続するようにしてみたのですが、そこで、私には理解できない挙動が起こりました。
問題を切り出すための最小限のソースを掲載します。
###index.html
html
1<!DOCTYPE html> 2<html> 3<head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> 6 <title>test</title> 7 <script src="/socket.io/socket.io.js"></script> 8 <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> 9 <script src="client.js"></script> 10</head> 11<body> 12 <h1>test</h1> 13 <div id="inputform"> 14 <input placeholder="部屋番号" id="RoomNumber"> 15 <input placeholder="ハンドルネーム" id="handlename"> 16 <button onclick="EnterRoom();" id="btnEnterRoom">入室</button> 17 </div> 18 <div id="message"></div> 19</body> 20</html>
###client.js
Javascript
1const socket = io.connect(); 2socket.on('disconnect', () => { 3 console.log("disconnect"); 4 $("#inputform").show(); 5}); 6 7socket.on('connect', () => { 8 var strMessage; 9 console.log("connected"); 10 socket.on('enter', (strMessage) => { 11 alert(strMessage); 12 $("#inputform").hide(); 13 $("#message").prepend(strMessage+"<br>"); 14 }); 15}) 16 17function EnterRoom() { 18 var roomID = $('#RoomNumber').val(); 19 var name = $('#handlename').val(); 20 var data ={}; 21 data.roomID = roomID; 22 data.name = name; 23 if (roomID) { 24 socket.emit('enter1', data); 25 } else { 26 alert("部屋番号を入力して下さい"); 27 } 28}
###server.js
Javascript
1const http = require('http'); 2const express = require('express'); 3const socketIO = require('socket.io'); 4const url = require('url').URL; 5const app = express(); 6const server = http.Server(app); 7const io = socketIO(server); 8const PORT = process.env.PORT || 3000; 9 10app.get('/', function (req, res) { 11 res.sendFile(__dirname + '/public/index.html'); 12}); 13app.get('/client.js', function (req, res) { 14 res.sendFile(__dirname + '/public/client.js'); 15}); 16 17io.on('connection', (socket) => { 18 var roomID; 19 var name; 20 console.log('connected'); 21 socket.on('disconnect', function () { 22 console.log(name + "さんが退出しました"); 23 io.to(roomID).emit('enter', name + "さんが退出しました"); 24 }); 25 socket.on('enter1', (data) => { 26 console.log(data); 27 roomID = data.roomID; 28 name = data.name; 29 socket.join(roomID); 30 console.log(name+"さんが"+roomID + "に入室しました"); 31 io.to(roomID).emit('enter', name + "さんが入室しました"); 32 }) 33}) 34 35server.listen(PORT, () => { 36 console.log('server starts on port: %d', PORT); 37});
##挙動
- まず、スマホでサーバーに接続し、ルーム番号とハンドルネームを入れて、roomに入ります。
ルーム番号とハンドルネームを入力するフォームは、非表示になります。
- スマホをスリープにして、スリープを解除すると、サーバーから切断されているので、サーバーのconsoleに、「○○さんが退出しました」と出力されます。
- client.jsの下の部分が発火し、ルーム番号とハンドルネームを入力するフォームを再表示します。
javascript
1socket.on('disconnect', () => { 2 console.log("disconnect"); 3 $("#inputform").show(); 4});
- 再度、roomに入ります。すると、client.jsの下の部分が、2回発火します。
javascript
1socket.on('enter', (strMessage) => { 2 alert(strMessage); 3 $("#inputform").hide(); 4 $("#message").prepend(strMessage+"<br>"); 5 });
- なお、上のclient.jsの部分に対応する、server.jsの下の部分は、1回しか発火しません。
javascript
1socket.on('enter1', (data) => { 2 roomID = data.roomID; 3 name = data.name; 4 socket.join(roomID); 5 console.log(name+"さんが"+roomID + "に入室しました"); 6 io.to(roomID).emit('enter', name + "さんが入室しました"); 7 })
-
さらに、スマホをスリープにして、スリープを解除して、再度roomに入ると、今度は、client.jsの該当部分が3回発火します。やはり、それに対応するserver.jsの部分は、1回しか発火しません。
-
以下、スリープ→解除 を繰り返すと、発火する回数が1回ずつ増えます。
-
明示的に、socket.leave(room名)して、再度roomに入るときは、上の現象は起こりません。接続が切れて、強制的にroomからleaveさせられるときに発生します。
原因が分からず、対処できなくて困っています。どなたか、分かる方、助けて下さい!!
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。