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

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

新規登録して質問してみよう
ただいま回答率
85.48%
HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

Node.js

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

Socket.IO

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

JavaScript

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

Q&A

解決済

3回答

1466閲覧

Socket.IOのクライアントを切断しても、今まで接続されていた分イベントが飛ぶ

kishi_kun

総合スコア26

HTML5

HTML5 (Hyper Text Markup Language、バージョン 5)は、マークアップ言語であるHTMLの第5版です。

Node.js

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

Socket.IO

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

JavaScript

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

0グッド

1クリップ

投稿2017/11/28 08:26

編集2017/12/20 11:38

###前提・実現したいこと
socket.ioとNode.jsを用いて、あるディレクトリにファイルが追加された時
その内容をイベントとしてクライアントに送るシステムを構築しています。

###発生している問題・エラーメッセージ
下記該当のソースコードにあるようなコードを記述しているのですが
クライアントの接続を切断してもsocket.idが廃棄されず、今まで接続していたクライアント全てに飛ばしているような
挙動を示します。
例)3回ブラウザを更新すると、4回分のイベントが発行されているような挙動
どのように修正すれば、切断時にsocket.idが廃棄され、現在接続しているクライアントのみに
イベントを飛ばすようになるのでしょうか。

###該当のソースコード

JavaScript

1//lib 2var express = require('express') 3var app = express(); 4var chokidar = require('chokidar'); 5var fs = require('fs'); 6var server = require ('http').Server(app); 7var io = require('socket.io')(server); 8var filepath = require('path'); 9 10let clients = {}; 11 12var watcher = chikidar.watch('./***/',{ 13 ignored:/[/\]./, 14 persistent:true, 15 alwaysStat:true, 16 } 17}); 18 19app.get('/',req,res)=>{ 20 res.SendFile(__dirname + './***.html'); 21}); 22 23io.on('connection',(socket)=>{ 24 clients[socket.id]= socket; 25 console.log(socket.id+'connected') 26 watcher.on('add',function(path){ 27  ///fsでファイルを読む処理をしています。 28 io.json.to(socket.id).emit(~~~); 29});// watcher 30socket.on('命令1',function(data){ 31 console.log(socket.id) 32 console.log('命令1が来た') 33  ///fsでファイルを消しています。 34}); 35socket.on('disconnect',(reason)=>{ 36 delete clients; 37 console.log(socket.id+'disconnected') 38}); 39});

###出力
例えば3回更新した時はこのように出力されます。

[Time] (socket.id1) connected [Time] (socket.id1) disconnected [Time] (socket.id2) connected [Time] (socket.id2) disconnected [Time] (socket.id3) connected

この時にemitさせるとこのように出力されます

[Time] (socket.id1) [Time] 命令1が来た [Time] (socket.id2) [Time] 命令1が来た [Time] (socket.id3) [Time] 命令1が来た

###試したこと
https://teratail.com/questions/97749
で回答頂いた通り、下記の様に変更した所Last few GCsが発生してしまいました。

/// ///fsでファイルを読むだけです。 while(socket.connected){ io.json.to(socket.id).emit(~~~); } });// watcher ///

###試したこと2
実際接続されているクライアントはどれだけあるかを確認するため、
以下の様にコードを変更し、確認しました。

io.on('connection',(socket)=>{ var info = io.sockets.client(); var count = Oblect.keys(info.connected).length console.log(info); //出力1 console.log(count); //出力2 clients[socket.id]= socket; watcher.on('add',function(path){ ・・・

結果としては出力1,2どちらも接続されている分しか出ませんでした。
例)2ブラウザで接続した際は、出力は2と出力
しかし、イベントを発火させた際、命令1が来たといった出力は変わらず今まで接続されていた
分出力されてしまいます。

###試したこと3
回答頂いた様に下記の様に実装致しました。

socket.on('disconnect',(reason)=>{ //delete clients; console.log(socket.id) delete clients[socket.id]; console.log(socket.id+'_disconnected') });

しかし、上記の部分の出力は以下のように、プロパティが消えず
更新しても今まで接続された分出力されてしまいます。

[Time] (socket.id1) [Time] (socket.id1_disconnected)

マルチポスト
Stack over flow

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

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

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

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

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

guest

回答3

0

自己解決

接続があるたびに watcher.on('add',...); でハンドラを登録して、削除していないのが問題でした。

以下の様にすることで動作しました。
回答頂いた皆様ありがとうございました。

watcher.on('add', function(path) { for (var id in clients) { io.json.to(id).emit(~~~); } }); io.on('connection', (socket) => { // ここでは watcher.on('add, ...); しない。 // ... socket.on('disconnect',(reason)=>{ delete clients[socket.id]; // ←ここも修正 console.log(socket.id+'disconnected') }); });

投稿2018/01/09 12:44

編集2018/01/09 12:45
kishi_kun

総合スコア26

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

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

0

delete clients;let clientsで宣言した全体を破棄させるような意味になるのでうまく動きません。

delete clients[socket.id];で当該ソケットのプロパティだけ消していきましょう。

投稿2017/12/15 11:35

maisumakun

総合スコア145184

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

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

kishi_kun

2017/12/20 11:34

回答ありがとうございます。追記にある形で実装を行ってみましたが、上手く行かず出力が変わりませんでした。何がいけないんでしょうか…
guest

0

切断時には実際にsocket.on('disconnect')は呼ばれているでしょうか?

投稿2017/11/30 12:11

TomokazuKozuma

総合スコア131

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

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

kishi_kun

2017/12/03 03:48

呼ばれていると思います。 disconnectの箇所のdelete clients;の上にconsole.logを入力すると、ちゃんとそのlog部が表示されるためです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問