2012-03-14 4 views
10

В производстве у меня есть игра, которая использует локальные переменные соединения для хранения состояния игры. Однако я замечаю, что если я простаиваю в течение определенного времени на соединении, он отключает и повторно соединяет, который теряет текущее состояние. Во время моих тестов на локальном хосте я никогда не замечал этого поведения. Является ли это нормальным поведением для соединений сокетов или что-то другое, вызывающее падение соединений.Соединения NodeJS + Socket.io: сброс/повторное подключение?

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

ответ

22

Ваша проблема в тайм-аутах сокетов. Если в определенном сокете нет активности, 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 here.

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

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

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

+0

Довольно умное решение, спасибо :) –

+2

Это умное решение, но оно будет поддерживать работу сервера и клиента с помощью пинг-понга :-(любое другое решение? –

0

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

+0

Вы правы, я отредактировал свой вопрос, чтобы принять это во внимание. – Moox

+0

То, что я сделал в своем приложении, - это обслуживание пользовательских данных за сеанс, а не соединение socket.io, и управление сеансами для каждого пользователя подключается/отключается. Что, BTW, вызывает всю проблему, почему socket.io включает данные для каждого сокета - Я не думаю, что эта функция действительно «совместима» с тем, как работает socket.io. Пытался использовать ее и отказаться от нее из-за постоянного отключения/повторного подключения. – Mark

Смежные вопросы