NodeJS + Socket.io соединения сбрасываются / переподключаются?
В производстве у меня есть игра, которая использует локальные переменные соединения для хранения состояния игры. Тем не менее, я замечаю, что, если я в течение определенного времени бездействую в соединении, оно отключается и повторно соединяется, что теряет текущее состояние. Во время моих тестов на локальном хосте я никогда не замечал такого поведения. Является ли это нормальным поведением для соединений с сокетами или что-то еще, вызывающее разрыв соединений.
Если это нормальное поведение, как это обычно обрабатывается? Должны ли значения соединения храниться глобально, чтобы их можно было восстановить, если пользователь отбросит / переподключится?
2 ответа
Ваша проблема заключается в тайм-аутах сокетов. Если на определенном сокете нет активности, 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 здесь.
РЕДАКТИРОВАТЬ: Марк прокомментировал, что если пользователь теряет соединение (соединение обрывается на его конце из-за проблем с интернетом), вы сможете восстановить пользователя до его последнего состояния.
Для этого лучше всего использовать уже широко используемый метод хранения пользовательских данных, файлов cookie и сеансов.
Очень хорошо сделанный урок о том, как это сделать, находится здесь. Хотя он использует Express для установки файлов cookie, вы можете сделать это с помощью чего угодно (я делаю это с помощью rails). Используя этот метод, вы можете сохранить пользовательские данные в файле cookie и извлечь их во время рукопожатия. Оттуда вы можете просто получить доступ к данным, используя socket.handshake.data
,
Что вам нужно сделать, это создать или идентифицировать сеанс для (повторного) соединения. Вы можете уменьшить количество переподключений в ответе Moox, приведенном выше, но он все еще не является отказоустойчивым - например, пользователь теряет соединение Wi-Fi на некоторое время и т. Д. Другими словами - поддерживает метаданные пользователя для сеанса, а не для сокета, и ожидает случайных отключений и повторных подключений.,