Подтвердить что ты не робот

Как я могу обработать событие Close в Socket.io?

Я делаю простую онлайн-игру, основанную на Web. игра использует Socket.io для взаимодействия друг с другом. но я столкнулся с проблемой.

думаю о следующей ситуации. Я запустил сервер Socket.io. один игрок делает комнату, а другой игрок входит в комнату. они играли в игру некоторое время.. но один игрок так разозлился и закрыл вкладку игры.

в этой ситуации, как я могу получить событие, которое один клиент был закрыт браузером на стороне сервера?

согласно googling, люди говорят так: "использовать событие закрытия браузера, например onBeforeUnload"

но я знаю, что браузер не поддерживает событие onBeforeUnload. так что я хочу решения о проверка события отключения клиента на стороне сервера.

в серверной консоли Socket.io(nodeJS), когда клиентское соединение закрыто, консоль скажет следующее:

отладка - отбрасывание транспорта

Моя версия nodeJS 0.4.10, а версия Socket.io - 0.8.7. и оба работают в Linux.

Кто-нибудь может помочь?

коды сокращений:

var io = require ( "socket.io" ).listen ( 3335 );
io.sockets.on ( "connection" , function ( socket )
{
  socket.on ( "req_create_room" , function ( roomId ) 
  {
    var socketInstance = io
    .of ( "/" + roomId )
    .on ( "connection" , function ( sock )
    {
       sock.on ( "disconnect" , function () 
       {
          // i want this socket data always displayed...
          // but first-connected-client doesn't fire this event ..
          console.log ( sock );
       }
    });
  });
});
4b9b3361

Ответ 1

Обновление: Я создал сообщение в блоге для этого решения. Любая обратная связь приветствуется!

Я рекомендую использовать опцию "sync disconnect on unload" для Socket IO. У меня были подобные проблемы, и это действительно помогло мне.

На клиенте:

var socket = io.connect(<your_url>, {
'sync disconnect on unload': true });

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

Ответ 2

Там событие disconnect, которое срабатывает всякий раз, когда соединение socket.io умирает (обратите внимание, что вам это нужно, потому что у вас все еще может быть страница wep, но что, если ваше интернет-соединение умирает?). Попробуйте следующее:

var io = require('socket.io').listen(80);

io.sockets.on('connection', function (socket) {
  socket.on('disconnect', function () {
    io.sockets.emit('user disconnected');
  });
});

на вашем сервере. Взято из веб-сайт Socket.IO.

//EDIT

Итак, я посмотрел ваш код и сделал несколько тестов у себя дома. Я получил те же результаты, что и вы, и здесь мои объяснения. Вы пытаетесь сделать Socket.IO очень динамичным, динамически заставляя его слушать разные URL-адреса (которые добавляются во время выполнения). Но когда происходит первое подключение, сервер не прослушивает другой URL-адрес. Кажется, что именно в этот момент (когда соединение принято) обработчик disconnect установлен для первого соединения и не обновляется позже (обратите внимание, что Socket.IO не создает новые соединения, когда вы вызываете io.connect много раз в клиентская сторона). В целом это кажется ошибкой! Или, может быть, есть какое-то причудливое объяснение, почему это поведение должно быть таким, каким оно есть, но я этого не знаю.

Позвольте мне рассказать вам еще кое-что. Прежде всего это динамическое создание слушателей, похоже, не является хорошим способом. На мой взгляд, вы должны сделать следующее: хранить существующие комнаты и использовать один URL для всех. Удерживайте идентификатор комнаты, и когда вы выбрали, например, событие message от клиента, добавьте идентификатор комнаты в данные и обработайте это одним обработчиком message на сервере. Я думаю, вы поняли. Нажимайте динамическую часть на данные, а не на URL. Но я могу ошибаться, по крайней мере, мое мнение.

Другое дело, что написанный вами код кажется плохим. Обратите внимание, что запуск .on('connection', handler) много раз заставит его срабатывать много раз. Обработчики складываются один на другой, они не заменяют друг друга. Так вот как я мог бы реализовать это:

var io = require("socket.io").listen(app);
var roomIds = [];

function update_listeners(id) {
    io.of("/"+id).on("connection", function(socket) {
        console.log("I'm in room " + id);
        socket.on("disconnect", function(s) {
           console.log("Disconnected from " + roomId);
        });            
    });
}

var test = io.sockets.on("connection", function(socket) {
    console.log("I'm in global connection handler");
    socket.on("req_create_room", function(data) {
        if (roomIds.indexOf(data.roomId) == -1 ) {
            roomIds.push(data.roomId);
            update_listeners(data.roomId);    
        }
        test.emit("room_created", {ok:true}); 
    });
    socket.on("disconnect", function(s) {
        console.log("Disconnected from global handler");
    });
});

Имейте в виду, что проблема с созданием подключений до того, как будут определены слушатели, все равно будет иметь место.