Socket.IO処理切断イベント


88

この切断イベントを処理できません。ソケットがクライアントに送信されない/クライアントが応答しない理由がわかりません。

サーバ

io.sockets.on('connection', function (socket) {

  socket.on('NewPlayer', function(data1) {

    online = online + 1;
    console.log('Online players : ' + online);
    console.log('New player connected : ' + data1);
    Players[data1] = data1;
    console.log(Players);

  });

  socket.on('DelPlayer', function(data) {

    delete Players[data];
    console.log(Players);
    console.log('Adios' + data);

  });

  socket.on('disconnect', function () {

      socket.emit('disconnected');
      online = online - 1;

  });

});

クライアント

 var socket = io.connect('http://localhost');

    socket.on('connect', function () { 

        person_name = prompt("Welcome. Please enter your name");

        socket.emit('NewPlayer', person_name);

        socket.on('disconnected', function() {

            socket.emit('DelPlayer', person_name);

        });

    });

ご覧のとおり、クライアントが切断すると、Arrayオブジェクト[person_name]は削除されますが、削除されません。


他の方法を試してみてください。最初にプレーヤーを削除してから切断します。サーバーから切断すると、サーバーはクライアントが発行するイベントを受信できなくなるためです。プレーヤーではなくソケットを追跡します。これにより、プレーヤーを簡単に削除できます。
code-jaff 2013年

プレーヤーを削除してから切断するにはどうすればよいですか?プレーヤーがいつ切断されるかを知るにはどうすればよいですか?
raggaer 2013年

4
クライアントでのイベントは'disconnect'代わりにすべきではありません'disconnected'か?
シャーロック

1
OPの元のクライアントコードの@Sherlockは、切断されたロジックのためにサーバーサイドでトリガーしていたカスタムイベントをリッスンしようとしていました。「disconnect」は確かに組み込みの切断イベントですが、発生している問題に直接寄与するものではありません。
ジョン教会

回答:


169

わかりました。接続したソケットを使用して名前トラックでプレーヤーを識別する代わりに。あなたは次のような実装を持つことができます

サーバ

var allClients = [];
io.sockets.on('connection', function(socket) {
   allClients.push(socket);

   socket.on('disconnect', function() {
      console.log('Got disconnect!');

      var i = allClients.indexOf(socket);
      allClients.splice(i, 1);
   });
});

これがあなたが別の方法で考えるのに役立つことを願っています


90
allClients.splice(i, 1)要素を削除するために使用することをお勧めします。delete allClients[i]アレイの位置をundefined
Yves

1
なぜそれは機能しているのに、名前付きの追跡ソリューションが機能していないのですか?
sha1 2014年

これは私にはうまくいきません。ここでiは毎回-1の値を取得しました。何が起こっているのか教えていただけますか。
Vinit Chouhan 2015

1
@VinitChouhanおそらく、実際の問題とは別の質問をする必要があります。
code-jaff 2015

-1の値を取得した場合、それは存在しないソケットを接続しようとしていることを意味します(誰かが切断しましたが、その人をまだallClientsアレイに登録していません)。if (i === -1)return;スプライスを試みる前に、戻ってください。
Koen B.

23

@ sha1のように、なぜOPのコードが機能しないのか疑問に思っている人のために-

サーバー側でプレーヤーを削除するためのOPのロジックは、DelPlayerイベントのハンドラーにあり、このイベント(DelPlayer)を発行するコードは、disconnectedクライアントのイベントコールバック内にあります。

このdisconnectedイベントを発行するサーバー側のコードdisconnectは、ソケットが接続を失ったときに発生するイベントコールバック内にあります。ソケットはすでに接続を失っているため、disconnectedイベントはクライアントに到達しません。


受け入れられたソリューションは、disconnectサーバー側でイベントのロジックを実行します。これは、ソケットが切断されたときに起動されるため、機能します。


6

マップまたはセットを作成し、接続された各ソケットに設定された「接続時」イベントを使用して、逆に「切断後」イベントで、前に作成したマップからそのソケットを削除します

import * as Server from 'socket.io';

const io = Server();
io.listen(3000);

const connections = new Set();

io.on('connection', function (s) {

  connections.add(s);

  s.once('disconnect', function () {
    connections.delete(s);
  });

});

1
そして、ベテランからの説明とコメントを含む詳細な回答を期待するでしょうが、私たちはコードの束だけで解決する必要があると思います
Cemal

質問があれば教えてください、答えを書いたのを覚えていません
Alexander Mills

1
実は何の質問もありません。コメントを使用し、回答に説明を入れて、だれでも(少なくともほとんどの場合)あなたを悩ませることなくあなたの例を理解できるようにすることをよく知っている著者にとって、それは建設的な批判にすぎませんでした。とにかく、幸せな新年...
ジェマル

0

また、ソケットIDを使用して、このようにプレーヤーリストを管理することもできます。

io.on('connection', function(socket){
  socket.on('disconnect', function() {
    console.log("disconnect")
    for(var i = 0; i < onlineplayers.length; i++ ){
      if(onlineplayers[i].socket === socket.id){
        console.log(onlineplayers[i].code + " just disconnected")
        onlineplayers.splice(i, 1)
      }
    }
    io.emit('players', onlineplayers)
  })

  socket.on('lobby_join', function(player) {
    if(player.available === false) return
    var exists = false
    for(var i = 0; i < onlineplayers.length; i++ ){
      if(onlineplayers[i].code === player.code){
        exists = true
      }
    }
    if(exists === false){
      onlineplayers.push({
        code: player.code,
        socket:socket.id
      })
    }
    io.emit('players', onlineplayers)
  })

  socket.on('lobby_leave', function(player) {
    var exists = false
    for(var i = 0; i < onlineplayers.length; i++ ){
      if(onlineplayers[i].code === player.code){
        onlineplayers.splice(i, 1)
      }
    }
    io.emit('players', onlineplayers)
  })
})
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.