Как стать автором
Обновить

Браузерный мультиплеер без сервера

Время на прочтение3 мин
Количество просмотров20K

Про технологию WebRTC в последнее время пишут много. Она позволяет обеспечить взаимодействие двух клиентов без специализированного сервера между ними, но нужда в сервере отпадает только после установки соединения. А на этапе установки самого соединения некоторые серверные ресурсы все еще нужны. Можно ли избавиться от потребности в сервере? Небольшой эксперимент в этом направлении под катом.

Потребность в сервере для rtc соединения возникает для двух целей. Первая – это сигнальный сервер, обеспечивающий обмен техническими сообщениями, необходимыми для поддержки самого протокола. К счастью, существует несколько готовых реализаций сигнального сервера и они уже открыты в сети к всеобщему удовольствию. Например, удобная библиотека peer.js в комплекте предлагает и облачный сигнальный сервер.
Соответственно об этой части вопроса можно не очень беспокоиться. Конечно же облачный сервер содержит кучу ограничений на количество соединений, но для начала этого вполне хватит.

Но есть вторая часть. Перед тем как начать работать с сигнальным сервером для соединения по rtc-протоколу участники должны обменяться идентификаторами. Идентификатор позволит сигнальному серверу выбрать нужного участника среди множества потенциальных адресатов. И доставка информации об идентификаторе лежит на плечах разработчика. Например, peer.js говорит нам «You're in charge of communicating the peer IDs between users of your site.». Я готового решения этой задачи не нашел.

Но что, если мы хотим установить связь со случайным абонентом? Для онлайн игры это может быть как раз то, что надо. Типовое решение для данного случая — создание специального сервера, который будет хранить базу зарегистрировавшихся идентификаторов. Это не слишком сложно, но хочется от этого сервера избавиться. Ведь никто не мешает обеспечить передачу этого идентификатора посредством rtc-соединения, открытого с фиксированным идентификатором. Идея такова:

  • Сначала клиент пытается соединиться (используем peer.js) с другим пользователем, используя предопределенный идентификатор. Этот идентификатор нужен только для вспомогательного временного соединения:

    signalPeer = new Peer(peer.options);
    signalConnection = signalPeer.connect('initial_peer');
    


  • Если соединиться удалось, то мы по этому rtc-каналу отправляем заветный идентификатор нашего пира, который будет использоваться для основного соединения:

    signalConnection.on('open',
         function() {signalConnection.send(mainPeerId); }
    );
    


  • Если же соединиться не удалось, то через некоторый таймаут, мы сами создаем канал с предопределенным идентификатором и ждем, когда к нам придет кто-нибудь еще:

    setTimeout(function(){
         if(!сonnected){
              signalPeer = new Peer('initial_peer', peer.options);
         }
    }, 3000);
    


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

Весь код умещается в полсотни строк. После оформления в виде мини-библиотеки (скачать можно здесь: github.com/bay73/puzzleduel/blob/master/randompeer.js) пользоваться им можно примерно так:

var peer = new Peer({key: key});
connectRandom(peer,
    function(connection) {
           // Сюда попадаем при успешном соединении
          connection.on('data'), function(data){ /* прием данных */});
          connection.send(data); /* отправка данных */
    },
    function() {
          // Сюда попадаем при неудаче соединения
    }
);


Посмотреть полный код и обеспечить нагрузочное тестирование игрушки, сделанной на его основе можно на github: bay73.github.io/puzzleduel. Может быть кому-то это скрасит ожидание окончания рабочей недели. Главная проблема — не все браузеры (и не все версии) WebRTC полностью поддерживают.

Ну а к тем, кто играть не хочет вопрос — будет ли подобный подход работать при ощутимой пользовательской нагрузке?
Теги:
Хабы:
+19
Комментарии23

Публикации

Изменить настройки темы

Истории

Работа

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн