Socket.io: почему socket.disconnect() на стороне клиента не запускает событие отключения на сервере?

Созданный на 4 нояб. 2015  ·  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

Самый полезный комментарий

ты тупой? вы ожидаете выброса на клиенте, но не выпускаете на сервере. иди на хуй отсюда

Все 23 Комментарий

Насколько я проверял, работает нормально. Как мы можем воспроизвести проблему?

Попробуйте зайти на страницу и быстро перезагрузить многократным нажатием кнопки F5.

Он отлично работает и для меня.

Какой браузер вы используете? Я использую последнюю версию Firefox, и когда я быстро перезагружаю пакет, «пользователь отключен» не работает :disappointed:

У меня тоже проблема. При этих действиях происходит отключение, но оно наступает гораздо позже, чем был перезапущен браузер.

Браузер: Chrome 55.0.2883.95 (64-разрядная версия)
сокет.ио: "^ 1.7.2"

Привет @ventaquil. У меня такая же беда, что событие разъединения не срабатывает при удерживании F5. Вы преодолели это?

@ giathinh910 не является ли событие disconnect запущенным после заданной задержки (это может быть связано с параметрами pingTimeout / pingInterval , задокументированными здесь )?

@darrachequesne Моя проблема такая же, как у @ventaquil , описанной выше: «Попробуйте войти на страницу и быстро перезагрузить, нажав много раз кнопку F5». Обычно, когда вы обновляете соединение сокета страницы, срабатывает «отключение», а затем снова «подключение». Я полагаюсь на эти 2 события, чтобы обновить количество онлайн-пользователей. Однако, если страница перезагружается достаточно быстро, «отключение» не сработает, что приведет к добавлению несуществующего идентификатора сокета пользователя. Эти нереальные люди будут удалены после pingTimeout конечно. В настоящее время я меняю способ сохранения идентификатора сокета, который будет показывать только онлайн-пользователя, а не номер сокета, и проблема может быть решена.

Я решил эту проблему таким образом. Я создал отправителя на клиенте, который вызывает сердцебиение на сервере.
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()

  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('подключение')
использовать
socket.once («подключиться»
.

то же самое здесь мой
socket.on («сообщение») { (dataArray, socketAck) -> Пусто в

  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")
  }
}

не возвращайте обратный вызов, если кто-нибудь знает, скажите мне

ты тупой? вы ожидаете выброса на клиенте, но не выпускаете на сервере. иди на хуй отсюда

Это настоящая негативная энергия, Ehsan666x.

Я решил эту проблему таким образом. Я создал отправителя на клиенте, который вызывает сердцебиение на сервере.
hbeat[socket.id] = Date.now();

Интересно, какое значение hbeat должно быть отправлено с клиентской стороны?

Вместо socket.disconnect() или socket.emit('disconnect') попробуйте socket.close(); на стороне клиента, и это должно вызвать событие 'disconnect' на стороне сервера. Это сработало для меня.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги