Есть ли рабочий пример, использующий nodeJS + peerJS?

Я провел весь день, пытаясь настроить свое приложение с помощью однорангового узла, но пока не смог добиться успеха.

Вот как выглядит файл js моего сервера:

const path = require('path');
const express = require('express');
const { ExpressPeerServer } = require('peer');
const app = express();
const PORT = process.env.PORT || 3000;

// set your static server
app.use(express.static(path.resolve(`${__dirname}/public`)));

// views
app.get('/', (req, res) => {
    res.sendFile(path.join(__dirname, 'views/index.html'));
});

// start listening
const server = app.listen(PORT);
console.log('Server is running localhost on port: ' + PORT);

// peerjs
const peerServer = ExpressPeerServer(server, {
    debug: true,
});

app.use('/peerjs', peerServer);

// listeners
peerServer.on('connection', (client) => {
    console.log("Server: Peer connected with ID:", client.id);
});

peerServer.on('disconnect', (client) => {
    console.log("Server: Peer disconnected with ID:", client.id);
});

Когда я запускаю приложение, оно говорит «Сервер: Peer connected with ID: ff1b23c0-9b67-49e3-8461-35405397d3b2», но через минуту оно говорит «Server: Peer disconnected with ID: ff1b23c0-9b67-49e3-8461-35405397d3b2».

Кроме того, мне не удалось подключить сервер к клиенту. Функция peer.on('connection', function(conn) {} никогда не вызывается. Я могу что-то упустить.

Итак, я пытаюсь найти пример кода, который работает, но пока я не нашел ни одного работающего примера (с использованием nodeJS, express, peerJS).

Может ли кто-нибудь познакомить меня с любым рабочим примером приложения узла, использующего одноранговые узлы?

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


person Zack Lee    schedule 25.04.2020    source источник


Ответы (2)


Вот небольшой рабочий пример, я пробовал это сам.

Ваш внутренний экспресс-сервер:

const express = require('express');
const { ExpressPeerServer } = require('peer');
const cors = require('cors');

const app = express();

app.use(cors());

app.get('/', (req, res, next) => res.send('Hello world!'));

const server = app.listen(9000);

const peerServer = ExpressPeerServer(server, {
  debug: true
});

app.use('/peerjs', peerServer);

peerServer.on('connection', (client) => { console.log('client connected');});
peerServer.on('disconnect', (client) => { console.log('client disconnected');});

И ваш интерфейсный код для подключения к вышеуказанному одноранговому серверу:

<html>
<head>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/peer.min.js"></script>
</head>
<body>
    <script>
        const peer = new Peer('someid', {
          host: 'localhost',
          port: 9000,
          path: '/peerjs'
        });
    </script>
</body>
</html>
person Hamza Arshad    schedule 01.05.2020

Я только что закоммитил полный рабочий пример работы peerjs с nodejs на github здесь:

. Я потратил много времени, пытаясь следовать множеству руководств, и, похоже, ни одно из них не работает для меня. Играя с ним и читая в группе телеграмм клиента peerjs, что люди заставляют приложения работать, добавляя задержки в случайных местах с кодом, блокирующим функции сна, я понял, что это проблема времени. Но забавно, как работает мой мозг, как обычно я проснулся посреди ночи с решением. Вот что происходило со мной с большинством руководств. Чтобы отвечать на вызовы, им нужно сначала настроить прослушиватель событий peer.on('call',(call) => {...}), а затем ответить на вызов с помощью call.answer(stream) внутри этой функции.

Поскольку для ответа на вызов им требуется локальный поток, все примеры, которые я нашел, вызывают

    navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream) {
  /* use the stream */
})
.catch(function(err) {
  /* handle the error */
});

или они используют конструкцию async/await и вызывают:

async function getMedia(constraints) {
  let stream = null;

  try {
    stream = await navigator.mediaDevices.getUserMedia(constraints);
    /* use the stream */
  } catch(err) {
    /* handle the error */
  }
}

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

navigator.mediaDevices
  .getUserMedia({
  audio: true,
  video: true,
})
.then((stream) => {
  myVideoStream = stream;
  addVideoStream(myVideo, stream);
  peer.on(“call”, (call) => {
    call.answer(stream);
    const video = document.createElement(“video”);
    call.on(“stream”, (userVideoStream) => {
      addVideoStream(video, userVideoStream);
      });
    });
  socket.on(“user-connected”, (userId) => {
      connectToNewUser(userId, stream);
  });
});

В чем проблема? Простой, когда клиент-получатель отвечает клиенту-инициатору, он сначала информирует одноранговый сервер о том, что хочет подключиться к той же комнате, механизм сигнализации для информирования клиента-инициатора о том, что клиент-адресат хочет подключиться, поступает к клиенту-инициатору самостоятельно. скорость. Ответом клиента-инициатора является вызов пункта назначения с использованием идентификатора, который одноранговый сервер предоставил через механизм сигнализации. Клиенту-инициатору нужен объект видео-/аудиопотока для совершения звонка, который он уже получил, когда впервые создал комнату, задолго до получения уведомления через сигнальный механизм о том, что в комнате есть кто-то еще, кому можно позвонить. Таким образом, вызов может происходить очень быстро (или очень медленно, если передача сигналов медленная, в целях этого обсуждения мы будем предполагать, что передача сигналов очень быстрая), поэтому вызов клиента-получателя от клиента-инициатора выполняется за несколько миллисекунд. . Но нет никакой гарантии, что клиент-инициатор готов принять этот вызов, вполне может быть ситуация, когда он только что запустился, подключился к одноранговому серверу для получения и идентификатора и теперь ожидает обещания от getUserMedia(). метод возврата. Таким образом, НЕТ гарантии, что вызов поступит после того, как клиент-получатель получит доступ к своему потоку и, таким образом, будет настроен обработчик события «вызов». Поэтому событие может быть получено до того, как существует обработчик. Затем целевой клиент будет ждать вечно (как это случилось со мной с учебными пособиями), создавая впечатление, что ничего не работает. Что я изменил, чтобы заставить его работать, так это заставить peer.on('call', async (call) =› {... немедленно, следовательно, запустить обработчик события call до того, как произойдет какое-либо подключение к серверу. Затем внутри обработчика событий дождитесь возврата потока следующим образом:

peer.on("call", async (call) => {
    let stream = null;
    console.log('*** "call" event received, calling call.answer(strem)');
    // Obtain the stream object
    try {
        stream = await navigator.mediaDevices.getUserMedia(
            {
                audio: true,
                video: true,
            });
        // Set up event listener for a peer media call -- peer.call, returns a mediaConnection that I name call        
        // Answer the call by sending this clients video stream --myVideo-- to calling remote user
        call.answer(stream);
        // Create new DOM element to place the remote user video when it comes
        const video = document.createElement('video');
        // Set up event listener for a stream coming from the remote user in response to this client answering its call
        call.on("stream", (userVideoStream) => {
            console.log('***"stream" event received, calling addVideoStream(UserVideoStream)');
            // Add remote user video stream to this client's active videos in the DOM
            addVideoStream(video, userVideoStream);
        });
    } catch (err) {
        /* handle the error */
        console.log('*** ERROR returning the stream: ' + err);
    };
});

Надеюсь, это поможет, так что никому больше не придется проходить через это снова!

person Julio Spinelli    schedule 20.07.2021