Socket.io: クライアント側のsocket.disconnect()がサーバーで切断イベントを発生させないのはなぜですか?

作成日 2015年11月04日  ·  23コメント  ·  ソース: socketio/socket.io

これが私のコードです:

クライアント側

 var socket = io.connect('http://' + serverAddress ,{ reconnection: false, forceNew: true  }  );

 socket.emit('monitorAddedNotify' , { video: sourceVideo , socketId: socket.id});

 socket.on('disconnectThatSoc', function(){
    socket.disconnect();
});

サーバ側:

  io.on('connection', function (socket) {
    console.log('a user connected');


    socket.on('disconnect', function () {
        console.log('user disconnected');
    });
 });

socket.disconnect()メソッドが機能しないのはなぜですか?

Unable to reproduce

最も参考になるコメント

あなたは馬鹿ですか? クライアントでのemitを待機していますが、サーバーでのemitは待機していません。 ここから性交

全てのコメント23件

私がテストした限り、それはうまくいきます。 どうすれば問題を再現できますか?

ページに入り、F5ボタンを何度も押して高速リロードしてみてください。

それは私にとってもうまくいきます。

どのブラウザを使用していますか? 最新のFirefoxを使用していますが、bageを高速でリロードすると、「ユーザーが切断されました」が機能しません:失望:

私も問題があります。 これらのアクションでは、切断されますが、ブラウザを再起動するよりもはるかに遅くなります。

ブラウザ:Chrome 55.0.2883.95(64ビット)
socket.io: "^ 1.7.2"

こんにちは@ventaquil。 F5を押しているときに切断イベントが発生しないのと同じ問題です。 これを乗り越えましたか?

@ giathinh910は、指定された遅延の後に発生したdisconnectイベントではありませんか(これは、ここに記載されているpingTimeout / pingIntervalオプションに関連している可能性があります)?

@darrachequesne私の問題は、上記の@ventaquilと同じです。「ページに入り、F5ボタンを何度も押して高速リロードしてみてください」。 通常、ページソケット接続を更新すると、「切断」が発生し、次に「接続」が再度発生します。 オンラインユーザーの数を更新するために、これら2つのイベントに依存しています。 ただし、ページの再読み込みが十分に速い場合、「切断」は実行されないため、存在しないユーザーソケットIDが追加されます。 もちろん、これらの非現実的な人々はpingTimeoutの後に削除されます。 現在、ソケットIDの保存方法を変更しました。これにより、ソケットの数ではなく、オンラインユーザーのみが表示され、問題を解決できます。

私はこの問題をこのように処理しました。 サーバーでハートビートを呼び出しているクライアントでemit送信者を作成しました。
socket.on("heartbeat", function() { // console.log('heartbeat called!'); hbeat[socket.id] = Date.now(); setTimeout(function() { var now = Date.now(); if (now - hbeat[socket.id] > 5000) { console.log('this socket id will be closed ' + socket.id); if (addedUser) { --onlineUsers; removeFromLobby(socket.id); try { // this is the most important part io.sockets.connected[socket.id].disconnect(); } catch (error) { console.log(error) } } } now = null; }, 6000); });

私はこのコード関数を呼び出すことができました:

io.sockets.connected[socket.id].disconnect();

これはまだ起こります。 F5/リフレッシュである必要はありません。 タブを開いて、特定の段階ですぐに閉じると、切断がトリガーされなくなります。 特にローカルで実行している場合、ソケットは非常に高速であるため、再現するのは困難です。 バックグラウンドでタブを開き、他のタブを開いておくと、問題を(ローカルで)再現するのに役立つことに気付きました。 これは対処すべき重要なバグだと思います。

ここで同じ問題があります。 これは私のゲームサーバーでゴーストゲームを作成しています

たぶん、手動でクライアントを切断するために、いくつかの放出を伴う関数を使用することができます。
これが役立つかどうかはわかりませんが、私は何かを得たと思います...多分...

クライアント

function ManualSocketDisconnect() {
    socket.emit("manual-disconnection", socket.id);

    socket.close();

    console.log("Socket Closed. ");
}

サーバー

io.on("connection", function(socket) {
    console.log("User " + socket.id + " Connected. ");

    socket.on("manual-disconnection", function(data) {
        console.log("User Manually Disconnected. \n\tTheir ID: " + data);
    });
});

申し訳ありませんが、コードにいくつかの穴を残した可能性があります。 私はプロではありません。 🙁

私は同じ問題に直面しています!
ReactJS-ExpressJSで例を示します。

これがイベントを発生させる状況であり、 componentWillUnmount()にカプセル化されています。

componentWillUnmount()から発生する2つのイベントを比較します

  1. newMessage :-これは特定の部屋にメッセージをブロードキャストします
  2. disconnect :-(うまくいくといいのですが、うまくいきません)このイベントリスナーには、切断されるコールバックがあります。 コールバックがヒットしたかどうかを確認するために、 console.log()を含めました。

さて、ここに行きます:-
クライアント:-

これらのイベントが発生しています:-

  componentDidMount() {
    console.log(this.props)
    chat.emit('authenticate', {
      token: localStorage.getItem('auth'),
      refreshToken: localStorage.getItem('refresh'),
      projectId: this.props.projectId,
      userId: this.props.userId,
    });
    chat.on('newMessage', (messageData) => {
      console.log('------------newMessageReceived-------------');
      this.props.messageReceived({ messages: this.props.messages, messageData }, () => {
        console.log('callback');
        this.setState({
          messages: this.props.messages
        })
      })
      console.log(messageData);
    })
  }

次のイベントは発生しません。

  componentWillUnmount() {
    chat.emit('disconnect','just disconnect);
  }

次のイベントがトリガーされます(通常のメッセージイベントが発生するかどうかをテストするだけです)

  componentWillUnmount() {
    chat.emit('newMEssage', {
      messageHeader: {
        sender: {
          user: {
            id: this.props.userId,
            name: this.props.name
          }
        }
      },
      messageBody: 'hello',
    });
  }

運がない

サーバ:-
これがexpressJSバックエンドのコードです

//次のinitializeChatSocketがapp.jsで呼び出されます

function initializeChatSocket(server) {
  projects.hasMany(projectTeam, { foreignKey: 'projectId' });

  const io = socketIO(server);
  const chat = io.of('/chat').on('connection', function (socket) {
    console.log(
      '----------------------------------------New Chat Connection Established-------------------------------------------------------------------------'
    );

    socket.auth = false;

    socket.on('authenticate', function (data) {
      console.log('\n\n\n\n', 'authenticate called', '\n\n\n\n', data, '\n\n\n');

      try {
        const dummyReq = {
          headers: {
            refreshtoken: data.refreshToken,
          },
        };
        console.log('\n\n\n\n', 'before verify', '\n\n\n\n');
        const userDetails = verifyJWTToken(dummyReq, data.token);
        console.log('\n\n\n\n', 'after verify', '\n\n\n\n');
        socket.userId = userDetails.userId;
        socket.projectId = data.projectId;

        projectTeam
          .findAll({
            where: {
              [Op.and]: {
                projectId: data.projectId,
                userId: data.userId,
              }
            }
          })
          .then(projects => {
            console.log('\n\n\n\n', JSON.stringify(projects), '\n\n\n\n');
            if (projects.length === 1) {
              socket.auth = true;
              socket.join(socket.projectId);
              console.log('User id:- ${userDetails.userId} linked to project id :- ${socket.projectId}');
            } else {
              console.log('User id:- ${userDetails.userId} not linked to project id :- ${socket.projectId}');
              throw { message: 'User not linked to project' };
            }
          });
      } catch (error) {
        console.log(String(error));

        socket.auth = false;
        socket.disconnect(String(error));
      }
    });

    socket.on('disconnectt', function() {
      console.log('Client Disconnecting'); // This is not being fired :/
      socket.removeAllListeners('newMessage');
      socket.removeAllListeners('disconnect');
      socket.removeAllListeners('authenticate');
      socket.removeAllListeners('connection');
      });

    socket.on('newMessage', async function (messageData) {
      console.log('-------------------------New Message----------------------', String(messageData));
      //TODO Save Message in Database

      try {
        socket.broadcast.to(socket.projectId).emit('newMessage', messageData);
        console.log('\n\n\n\n\n broadcast sent\n\n' + JSON.stringify(messageData) + '\n\n\n');
      } catch (error) {
        console.log('\n\n\n\n\n broadcast error\n\n\n\n\n');
        console.log(String(error));

        console.log(error);
        //TODO Handle Message Sending Error
      }
    });

  });
}

これはブラウザの問題ですか、それともスタックオーバーフローコミュニティから質問する必要がある他の問題ですか?

@manjotskこれまでに修正したかどうかはわかりませんが、サーバー側のコードでdisconnecttをリッスンしています(ダブルtに注意してください)が、フロントエンドが出力していますdisconnect 。 また、クライアントが切断したときにそのイベントがクライアントからサーバーに送信されることになっているため、おそらくdisconnectを発行したくないでしょう。

ipsの重複を防ぐために、切断イベントを発行するソケットに依存するコードがあります。切断が発生しないため、アプリをリロードするユーザーはすぐにブロックされます。

@manjotskこれまでに修正したかどうかはわかりませんが、サーバー側のコードでdisconnecttをリッスンしています(ダブルtに注意してください)が、フロントエンドが出力していますdisconnect 。 また、クライアントが切断したときにそのイベントがクライアントからサーバーに送信されることになっているため、おそらくdisconnectを発行したくないでしょう。
disconnecttは、私が使用していたなりすましのエイリアスでした。 ご指摘ありがとうございます。 両側でこれを再確認します。 そして、明らかに、実装は間違っていました! はっきりとした視界が得られました! ありがとう@nathanheffley👍 :)

@manjotskなに?

代わりにsocket.onceのみを使用してくださいsocket.on
「顧客レベル」。
例:
socket.on('connect')
使用する
socket.once('connect'

ここで同じ
socket.on( "message"){(dataArray、socketAck)-> Void in

  if let data = dataArray.first as? Data{
    do{
      let objc = try JSONDecoder.init().decode(GetChatConversation.self, from: data)
      completionHandler(objc,nil)
    }
    catch let error{
      return completionHandler(nil,error.localizedDescription)
    }
  }else{
    completionHandler(nil,"Cannot cast Array of Any to Data")
  }
}

誰か知っている人が教えてくれたら、コールバックを返さないでください

あなたは馬鹿ですか? クライアントでのemitを待機していますが、サーバーでのemitは待機していません。 ここから性交

それは本当の負のエネルギーです、Ehsan666x。

私はこの問題をこのように処理しました。 サーバーでハートビートを呼び出しているクライアントでemit送信者を作成しました。
hbeat [socket.id] = Date.now();

クライアント側からどのhbeat値を送信する必要があるのでしょうか。

socket.disconnect()またはsocket.emit('disconnect')の代わりに、クライアント側でsocket.close(); $を試してください。サーバー側で、 'disconnect'イベントがトリガーされます。 それは私のために働いた。

このページは役に立ちましたか?
0 / 5 - 0 評価