Соединения NodeJS + Socket.io: сброс/повторное подключение?

В производстве у меня есть игра, которая использует локальные переменные соединения для хранения состояния игры. Однако я замечаю, что если я простаиваю в течение определенного времени на соединении, он отключает и повторно соединяет, который теряет текущее состояние. Во время моих тестов на локальном хосте я никогда не замечал этого поведения. Является ли это нормальным поведением для соединений сокетов или что-то другое, вызывающее падение соединений.

Если это нормальное поведение, как это обычно обрабатывается? Должны ли данные соединения храниться глобально, чтобы они могли быть восстановлены, если пользователь сбросил/снова подключился?

Ответ 1

Ваша проблема связана с тайм-аутами сокетов. Если в определенном сокете нет активности, socket.io закроет его автоматически.

Легкое (и хакерское) исправление - отправить пульс подключенному клиенту для создания активности и остановить сокет от выключения времени.

Сервер:

function sendHeartbeat(){
    setTimeout(sendHeartbeat, 8000);
    io.sockets.emit('ping', { beat : 1 });
}

io.sockets.on('connection', function (socket) {
    socket.on('pong', function(data){
        console.log("Pong received from client");
    });
}

setTimeout(sendHeartbeat, 8000);

Клиент:

socket.on('ping', function(data){
      socket.emit('pong', {beat: 1});
    });

Дополнительная информация:

Вы можете получить дополнительную информацию о настройке socket.io здесь.

EDIT: Марк отметил, что если пользователь действительно потеряет соединение (соединение падает на его конец из-за проблем с Интернетом), вы должны иметь возможность восстановить пользователя до последнего состояния.

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

Очень хорошо сделанный учебник о том, как это сделать расположенный здесь. Хотя он использует экспресс для установки файлов cookie, вы можете сделать это с помощью чего-нибудь (я делаю это с использованием рельсов). Используя этот метод, вы можете хранить пользовательские данные в файле cookie и извлекать его во время рукопожатия. Оттуда вы можете просто получить доступ к данным с помощью socket.handshake.data.

Ответ 2

Что вам нужно сделать, это создать или идентифицировать сеанс за (повторное) соединение. Вы можете уменьшить количество повторных соединений на один ответ Moox выше, но он по-прежнему не защищен от сбоев - например, пользователь теряет соединение wifi для бит и т.д. Другими словами - поддерживайте метаданные пользователей за сеанс, а не за сокет, и ожидайте случайных отключений и повторных подключений.