Канал данных WebRTC открыт, но не отправляет никаких данных.

Вопрос или проблема

Я пытаюсь отправить данные через datachannel webrtc. Ниже мой код

//код клиентской стороны
 // Подключение к WebSocket серверу
      var ID = null;
      const ws = new WebSocket("ws://localhost:8080");
      // Настройка пирового соединения (UDP)
      const localConnection = new RTCPeerConnection();
      const dataChannel = localConnection.createDataChannel("sendChannel");

      document.getElementById("Send").addEventListener('click' , function(){
        console.log("Пытаюсь отправить сообщение...");
 dataChannel.send("Привет")
})
      // console.log(Object.getPrototypeOf(ws));
      ws.onopen = () => {
        console.log("Подключено к серверу");

        //const dataChannel = connection.createDataChannel("channel");

        localConnection.onicecandidate = (e) => {
          console.log("Новый ICE кандидат!" , localConnection.localDescription.type);
          ws.send(JSON.stringify({
                    type: "create"+ localConnection.localDescription.type,
                    data: {
                        id: ID,
                        sdp: localConnection.localDescription
                    }
                }))
         /* ws.send(JSON.stringify({
            type: "ICE",
            data: {
              sdp: localConnection.localDescription
            }
          }));*/
          //ws.send("[Сервер]: Новый Ice кандидат");
        };

        localConnection.onicecandidateerror = (e) => {
          console.warn("Ошибка: ICE кандидат", e);
        };

        dataChannel.onmessage = (e) =>
          console.log("сообщение получено!!!" + e.data);
        dataChannel.onopen = (e) => console.log("открыто!!!!");
        dataChannel.onclose = (e) => console.log("закрыто!!!!!!");

        // Отправить сообщение серверу
        ws.send(JSON.stringify({type: "findLobby" , "message": null}));
      };

      ws.onclose = () => {
        console.log("Отключено от сервера");
      };

      ws.onmessage =  (event) => {
       // console.log(Получено сообщение от сервера: ${typeof event.data});
        //if (typeof event.data !== "object") return;
        var data = JSON.parse(event.data);
        switch (data.type) {
          case "createOffer":
            console.log("Создание предложения!");
            localConnection.createOffer()
            .then(o => {
                //console.log(o);
                 localConnection.setLocalDescription(o);
               /* ws.send(JSON.stringify({
                    type: "createOffer",
                    data: {
                        sdp: o
                    }
                }))*/
            });
            break;

          case "createAnswer":
            console.log("Создание ответа!");
            console.log("Общедоступная сессия найдена: Вы сейчас подключаетесь...");
            localConnection.setRemoteDescription(data.data[1].sdp).then(a=> console.log(localConnection.remoteDescription, "Удаленное соединение настроено"))
            localConnection.createAnswer().then(a=>{
              console.log(a)
              localConnection.setLocalDescription(a).then(()=> {
                console.log('Локальное описание настроено: ',localConnection.localDescription)
                ws.send(JSON.stringify({
                type: "answer",
                data: {
                  sessionid: data.data[0],
                  sdp: localConnection.localDescription
                }
              }))
              });

            });
            break;

            case "acceptAnswer":
            console.log("Принять ответ: ",event.data)
            let datax = JSON.parse(event.data);
            let answer = datax.data.sdp;
            localConnection.setRemoteDescription(answer).then(a => {
              console.log("Установление соединения...");
             //dataChannel.send(JSON.stringify({message: "Привет" , data: datax}))
            })
            break;

          case "message":
            console.log(event.data)
            break;

            case "newclient":
              console.log("Новый клиент id" , event.data);
              ID = JSON.parse(event.data).id;
            break;

          default:
            console.log("Неверный тип");
            break;
        }
      };

Код серверной стороны (websocket)

const WebSocket = require('ws');

// Создание WebSocket сервера, прослушивающего порт 8080
const wss = new WebSocket.Server({ port: 8080 });
const freeUsers = new Map();
const connected = [];
const clients = new Map();

class PublicLobby{
  constructor(id){
    this.id = id;
    this.players = new Map();
    this.host = null;

  }
}

wss.on('connection', (ws) => {
  var sessionid = generateUniqueId();
  clients.set(sessionid , {
    isJoined: false,
    isFree: true,
    ws: ws,
    });
  // Отправить приветственное сообщение клиенту
  ws.send(JSON.stringify(
    {
      type: 'newclient',
      id: sessionid,
    }
  ))
  ws.send(JSON.stringify({type: 'message' , message: 'Добро пожаловать на WebSocket сервер!'}));

  // Слушать сообщения от клиента
  ws.on('message', (message) => {
    let m = JSON.parse(message);
    console.log("Свободные пользователи:" , freeUsers);
    //console.log("клиенты:" , clients);
    switch (m.type) {
        case "createoffer":
            if(clients.has(m.data.id)){
              let player = clients.get(m.data.id)
              player.sdp = m.data.sdp;

              if(freeUsers.has(m.data.id)){
                freeUsers.get(m.data.id).sdp = m.data.sdp;
              }
              else{
                freeUsers.set(m.data.id , {
                  isJoined: false,
                  isFree: true,
                  ws: player.ws,
                  ...m.data});

                  ws.send(JSON.stringify({type: "message" , message: "Создана новая сессия!" }));
              }

            }

            break;

            case "ICE":
             // console.log("Ice data:" , m.data);
              ws.send(JSON.stringify({type: "acceptAnswer" , message: "Ice ответ" , data: m.data}))
            break;

        case "createanswer":
          //console.log(m.data);
          const freeUser = freeUsers.entries().next().value;
          if (freeUser && !freeUser[1].ans) {
              freeUser[1].ws.send(JSON.stringify({ type: "acceptAnswer", message: "Ответ от клиента", data: m.data }));
              freeUser[1].ans = true;
          }
            break;
            case "findLobby":
                if(freeUsers.size > 0)
                    ws.send(JSON.stringify({ type: "createAnswer", message:"Лобби найдено, вы сейчас присоединяетесь.." , data: freeUsers.entries().next().value}));
                else
                    ws.send(JSON.stringify({ type: "createOffer", message:"Сессия не найдена (создание новой публичной сессии...)"}))
            break;
        default:
            break;
    }
  });

  // Обработка отключения клиента
  ws.on('close', () => {
    // freeUsers.get()
    console.log('Клиент отключен');
  });
});

function generateUniqueId() {
    return `session_${Math.random().toString(36).substr(2, 9)}`;
  }
console.log('WebSocket сервер работает на ws://localhost:8080');

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

не уверюсь, что не так с моим кодом.

Пожалуйста, помогите мне. спасибо

Ответ или решение

При работе с WebRTC Data Channel могут возникать различные проблемы, такие как: успешное открытие канала, но отсутствие отправки данных. Ваша ситуация указывает на то, что канал данных открыт, но сообщение не отправляется. Давайте рассмотрим возможные причины этой проблемы и способы их устранения.

1. Порядок установки соединения

Сначала необходимо убедиться, что оба конца соединения (клиент и сервер) корректно настроены и находятся в состоянии, когда можно обмениваться данными. Проверьте логи dataChannel.onopen, чтобы убедиться, что канал действительно открыт перед отправкой сообщения.

dataChannel.onopen = (e) => {
  console.log("Канал открыт!");
  // Теперь можно отправлять данные
  dataChannel.send("Hello");
};

2. Обработка сообщений

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

dataChannel.onmessage = (e) => {
  console.log("Сообщение получено: " + e.data);
};

3. Параметры ICE

Проблема с отправкой сообщения может быть связана с успехом процесса формирования ICE кандидатуры (Interactive Connectivity Establishment). Эффективность ICE-кандидатов влияет на установление соединения. Убедитесь, что оба интерфейса (клиент и сервер) обмениваются всеми ICE кандидатами после установления соединения. В вашем коде это делается в обработчике onicecandidate:

localConnection.onicecandidate = (e) => {
  if (e.candidate) {
    ws.send(JSON.stringify({ type: "ICE", candidate: e.candidate }));
  }
};

Убедитесь, что ваш сервер корректно обрабатывает ICE кандидаты и передает их другому участнику.

4. Синхронизация SDP

При работе с SDP (Session Description Protocol) важно, чтобы оба конца соединения согласовали свои параметры. Убедитесь, что вы корректно обмениваетесь SDP описаниями, и что взаимные описания настроены перед попыткой отправить данные по каналу:

localConnection.setRemoteDescription(data.data[1].sdp)
  .then(() => localConnection.createAnswer())
  .then(answer => localConnection.setLocalDescription(answer));

5. Состояние WebSocket

Проверьте соединение WebSocket перед отправкой сообщений через Data Channel. Возможно, код выполняется, но соединение еще не готово. Добавьте проверку состояния WebSocket, чтобы убедиться, что он открыт:

if (ws.readyState === WebSocket.OPEN) {
  // Отправляйте сообщения
}

Заключение

Для успешной передачи данных через WebRTC Data Channel убедитесь, что канал открыт, и вы правильно обрабатываете Ice кандидаты и SDP одновременно. Каждое сообщение должно отправляться только после успешного установления соединения, чтобы избежать потери данных.

Если после всех проверок проблема остается, рассмотрите использование отладочных инструментов для WebRTC, таких как webrtc-internals, которые могут помочь вам получить дополнительную информацию о состоянии соединения.

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

Оцените материал
Добавить комментарий

Капча загружается...