質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1940閲覧

Node.jsのチャット様のアプリで、接続が切れて再接続した際、roomにjoinするイベントが何度も発生する。

yiwsk

総合スコア39

Node.js

Node.jsとはGoogleのV8 JavaScriptエンジンを使用しているサーバーサイドのイベント駆動型プログラムです。

Socket.IO

Socket.IOはNode.js上で動くライブラリであり、すべてのブラウザとモバイルデバイスでリアルタイムのアプリを作動させる事を目的としています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2021/08/14 03:28

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させられるときに発生します。

原因が分からず、対処できなくて困っています。どなたか、分かる方、助けて下さい!!

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

自己解決

解決しました。

【Socket.io】クライアントから送信したメッセージがサーバ側に複数受信される

をヒントに、client.js の

javascript

1socket.on('connect', () => { ←削除 2…… 3})←削除

を削除したところ、きちんと動作しました。

投稿2021/08/14 04:52

編集2021/08/14 04:54
yiwsk

総合スコア39

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問