- PVSM.RU - https://www.pvsm.ru -
Однажды с коллегой столкнулись с проблемой реализации рилтайм мультиплеера на CoronaSDK. Сначала попробовали сервис pubnub.com, но со временем поняли, что не устраивает их latency (у них все через http) и цены. Не найдя ничего получше, решили на скорую руку создать на Node.js свой велосипед (или скорее самокат, потому как весь серверный код умещается в 90 строк с комментариями).
Назвали в шутку NoobHub. Распространяется под лицензией WTFPL.
Штука получилась весьма быстрой и, судя по отзывам пользователей, способной крутиться месяцами на сервере без перезапусков и утечек памяти. Системные требования: Node.js 0.6.x и выше (входит в стандартный пакет Ubuntu), никаких дополнительных модулей не требуется.
Если Вы пишете мобильное мультиплеер приложение на Lua используя CoronaSDK, Moai или Gideros, то есть хорошие новости: клиент под эти SDK отлично работает, бери и пользуйся.
Запустили сервер:
$ node server.js
На клиенте создали объект:
hub = noobhub.new({ server = "127.0.0.1"; port = 1337; });
Подписались на канал, в колбек-функции обрабатываем сообщение других участников:
hub:subscribe({
channel = "hello-world";
callback = function(message)
if(message.action == "ping") then
print("Pong!")
end;
end;
});
Отправили сообщение:
hub:publish({
message = {
action = "ping",
timestamp = system.getTimer()
}
});
Ключевым элементом Node.js скрипта является объект server, который слушает порт и реагирует на соединения. Для каждого из них создаётся socket с уникальным хешем для последующего поиска и удаления в случае необходимости.
Сокеты в свою очередь слушают события получения данных и закрытия соединения.
Они распознают два типа сообщений: __SUBSCRIBE____ENDSUBSCRIBE__ — подписка на канал,
__JSON__START_<_MESSAGE>__JSON__END__ — произвольное сообщение. При подписке сокет добавляется в пул CHANNELNAME и все последующие сообщения приходящие по данному каналу будут передаваться и новоприбывшему. Во втором случае тело MESSAGE будет адресовано всем подписчикам канала CHANNELNAME. Для отсоединения достаточно закрыть сокет на стороне клиента, а дальше сервер знает, что делать с дезертиром.
Получается, что один EventLoop ноды делает всю работу по получению данных и расфасовке их клиентам в сокеты. Если клиентов будет много, соответственно увеличенный цикл будет вносить задержку в доставку сообщений. Вопрос конечно, сколько надо клиентов чтобы просадка была хоть сколько-то заметной. При 2к CCU просадки latency не наблюдалось (больше у нас просто небыло), но я сомневаюсь что и 20к даст заметную просадку.
На клиенте все с точностью до наоборот, клиент подключается к socket серверу, подписывается на канал, и асинхронно слушает сообщения от других участников канала.
Есть автоматический reconnect & resubscribe при обрыве (облегчает жизнь юзерам с плохим коннектом на EDGE/3G).
В планах переписать сервер на новой версии ноды с поддержкой кластеров и доменов, чтобы увеличить способность к масштабированию.
Исходный код сервера и клиентов: https://github.com/Overtorment/NoobHub [2]
Автор: DreamerUA
Источник [3]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/node-js/52424
Ссылки в тексте:
[1] Durak HD: https://itunes.apple.com/app/durak-hd/id553841224
[2] https://github.com/Overtorment/NoobHub: https://github.com/Overtorment/NoobHub
[3] Источник: http://habrahabr.ru/post/208584/
Нажмите здесь для печати.