包括冰服务器时,WebRTC处于连接状态(远程候选甚至通过LAN也会引起问题)

大卫·卡兰南

我暂时RTCPeerConnection没有iceServers尝试解决以前的问题而是创建了一个

let peer = new RTCPeerConnection();

这在我的本地网络上运行良好。

但是,不在同一网络上的设备(例如4G上的移动设备)将无法连接。我记得我有一些重新添加iceServersRTCPeerConnection构造函数。

let peer = RTCPeerConnection(
  {
    iceServers: [
      {
        urls: [
          "stun:stun1.l.google.com:19302",
          "stun:stun2.l.google.com:19302",
        ],
      },
      {
        urls: [
          "stun:global.stun.twilio.com:3478?transport=udp",
        ],
      },
    ],
    iceCandidatePoolSize: 10,
  }
);

从那以后,我的WebRTC连接就一直处于连接状态。即使在我的本地网络上,也没有一个成功的连接。(不再是这种情况,请参见下面的编辑2

这是连接状态:

  • 冰候选人聚集。
  • 要约/答案已创建。
  • 通过我的信号服务成功发送了要约/答案和候选冰。
  • 我成功设置了远程和本地描述,并在任一端添加了候选冰。
  • 连接保持连接状态。
  • 大约30秒后,连接超时并失败。

编辑:似乎比我留下iceServers空白时,连接仍会收集一个ice候选对象,因此我假设我的浏览器(chrome)提供了默认的ice服务器。在这种情况下,只有我的自定义Ice服务器(如上所示)才引起问题,而不是浏览器默认设置。


编辑2:新观察

我添加了很多日志记录,只要有iceServers包含,我就会注意到一些东西

每当对等体A在一段时间内首次启动与对等体B的连接时,对等体B都会收集两个ice候选对象:1个本地主机候选对象和1个远程候选对象。如前所述,连接失败。

但是当我迅速尝试再次连接时...对等B仅收集了一个单独的ice候选对象:一个本地主机候选对象。不会收集远程候选人。我的第一个假设是我正在使用的STUN服务器(在这种情况下,很可能是Google的服务器)对其服务具有某种形式的速率限制。这种情况真正有趣的是,连接成功!!

远程候选人弄乱了连接,这有些不可思议。我希望这些新的细节会有所帮助。我被这个问题困扰了几个月!而且这两个设备都在我的LAN上,因此我希望远程候选对象绝对不会起作用。


对等A代码(发起方):

export class WebRTCConnection {
  private _RTCPeerConnection: any;
  private _fetch: any;
  private _crypto: any;

  private _entity: any;
  private _hostAddress: any;
  private _eventHandlers: ConnectionEventHandlers;
  private _peer: any;
  private _peerChannel: any;

  constructor({
    entity,
    hostAddress,
    eventHandlers,
    RTCPeerConnection,
    fetch,
    crypto,
  }: {
    entity: any,
    hostAddress: any,
    eventHandlers: ConnectionEventHandlers,
    RTCPeerConnection: any,
    fetch: any,
    crypto: any,
  }) {
    this._RTCPeerConnection = RTCPeerConnection;
    this._fetch = fetch;
    this._crypto = crypto;

    this._entity = entity;
    this._hostAddress = hostAddress;
    this._eventHandlers = eventHandlers;

    this._initPeer();
  }

  async _initPeer() {
    this._peer = new this._RTCPeerConnection(/* as shown in question */);

    let resolveOfferPromise: (value: any) => void;
    let resolveIceCandidatesPromise: (value: any[]) => void;
    
    let iceCandidatesPromise: Promise<any[]> = new Promise((resolve, _reject) => {
      resolveIceCandidatesPromise = resolve;
    });

    let offerPromise: Promise<any> = new Promise((resolve, _reject) => {
      resolveOfferPromise = resolve;
    });

    this._peer.onnegotiationneeded = async () => {
      let offer = await this._peer.createOffer();
      await this._peer.setLocalDescription(offer);
      resolveOfferPromise(this._peer.localDescription);
    };

    this._peer.onicecandidateerror = () => {
      // log error
    };

    let iceCandidates: any[] = [];

    this._peer.onicecandidate = async (evt: any) => {
      if (evt.candidate) {
        // Save ice candidate
        iceCandidates.push(evt.candidate);
      } else {
        resolveIceCandidatesPromise(iceCandidates);
      }
    };

    (async () => {
      // No more ice candidates, send on over signaling service
      let offer: any = await offerPromise;
      let iceCandidates: any[] = await iceCandidatesPromise;

      let sigData = // reponse after sending offer and iceCandidates over signaling service

      let answer = sigData.answer;
      await this._peer.setRemoteDescription(answer);

      for (let candidate of sigData.iceCandidates) {
        await this._peer.addIceCandidate(candidate);
      }
    })();

    this._peer.onicegatheringstatechange = (evt: any) => {
      // log state
    };

    this._peer.onconnectionstatechange = async () => {
      // log state
    };

    this._peerChannel = this._peer.createDataChannel("...", {
      id: ...,
      ordered: true,
    });

    this._peerChannel.onopen = () => {
      // log this
    };

    this._peerChannel.onmessage = (event: any) => {
      // do something
    };
  }

  send(msg: any) {
    this._peerChannel.send(
      new TextEncoder().encode(JSON.stringify(msg)).buffer,
    );
  }

  close() {
    if (this._peer) {
      this._peer.destroy();
    }
  }
}

对等B代码:

export class WebRTCConnection {
  constructor({ signalData, eventHandlers, RTCPeerConnection }) {
    this._eventHandlers = eventHandlers;

    this._peer = new RTCPeerConnection(/* as seen above */);

    this._isChannelOpen = false;

    this._peer.ondatachannel = (event) => {
      event.channel.onopen = () => {
        this._mainDataChannel = event.channel;
        event.channel.onmessage = async (event) => {
          // do something
        };
        this._isChannelOpen = true;
      };
    };

    this._peer.onicecandidateerror = () => {
      // log error
    };

    this._iceCandidates = [];
    this._isIceCandidatesFinished = false;
    this._iceCandidatesPromise = new Promise((resolve, _reject) => {
      this._resolveIceCandidatesPromise = resolve;
    });
    this._isAnswerFinished = false;
    this._isSignalDataSent = false;

    this._peer.onicecandidate = async (evt) => {
      if (evt.candidate) {
        // Save ice candidate
        this._iceCandidates.push(evt.candidate);
      } else {
        // No more ice candidates, send on over signaling service when ready
        this._isIceCandidatesFinished = true;
        this._resolveIceCandidatesPromise();
        this._sendSignalData();
      }
    };

    (async () => {
      let sigData = JSON.parse(signalData);

      let offer = sigData.offer;
      await this._peer.setRemoteDescription(offer);

      this._answer = await this._peer.createAnswer();
      await this._peer.setLocalDescription(this._answer);

      for (let candidate of sigData.iceCandidates) {
        await this._peer.addIceCandidate(candidate);
      }

      this._isAnswerFinished = true;
      this._sendSignalData();
    })();

    this._peer.onconnectionstatechange = async () => {
      // log state
    };
  }

  _sendSignalData() {
    if (false
      || !this._isIceCandidatesFinished
      || !this._isAnswerFinished
      || this._isSignalDataSent
    ) {
      return;
    }

    this._isSignalDataSent = true;

    this._eventHandlers.onSignal(JSON.stringify({
      answer: {
        type: this._answer.type,
        sdp: this._answer.sdp,
      },
      iceCandidates: this._iceCandidates,
    }));
  }

  send(msg) {
    this._mainDataChannel.send(new TextEncoder().encode(JSON.stringify(msg)));
  }

  close() {
    this._peer.destroy();
  }
}
大卫·卡兰南

问题是我正在使用Brave浏览器。

使用Chrome解决了所有问题。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

WebRTC处于连接状态

来自分类Dev

如何在服务器仍处于活动状态时检查浏览器连接?

来自分类Dev

与远程Redis服务器连接的问题

来自分类Dev

iOS冰上的WebRTC冰连接状态卡住

来自分类Dev

WebRTC冰候选人

来自分类Dev

无法连接到服务器(通过远程连接)

来自分类Dev

英特尔WebRTC 2.1.1服务器连接问题

来自分类Dev

连接到远程服务器并执行简单的数据库查询时出现问题

来自分类Dev

通过LAN IP地址连接WebSocket服务器

来自分类Dev

通过OpenVPN连接到服务器LAN

来自分类Dev

通过SSH连接LAN HTTP服务器

来自分类Dev

如何通过R连接到远程服务器?

来自分类Dev

从Windows通过X服务器远程连接到RHEL

来自分类Dev

使用JAVA通过FTP连接到远程服务器

来自分类Dev

从PHP页面连接远程服务器时出错

来自分类Dev

Cake PHP:由于浏览器缓存而引起的问题,站点在我的本地系统中正常运行,但是当移至远程服务器时却无法运行

来自分类Dev

如何在服务器仍处于活动状态的情况下检查浏览器连接?

来自分类Dev

在WSL 2上通过Docker连接到TCP服务器时出现问题

来自分类Dev

Regd:通过ODAC连接Oracle服务器时的性能问题

来自分类Dev

通过VPN连接时,FTP服务器连接被拒绝

来自分类Dev

我尝试连接到服务器时出现“远程服务器超时”异常

来自分类Dev

在18.04.3上的〜120,000处于活动状态后,服务器停止接受连接

来自分类Dev

从远程服务器上的本地服务器执行IMPDP命令时出现问题

来自分类Dev

通过ssh连接到远程服务器时,以Vi模式运行zsh(oh-my-zsh)

来自分类Dev

System.Net.WebException:无法连接到远程服务器-仅LAN中的服务器

来自分类Dev

如何通过SSH连接通过远程服务器连接到Internet

来自分类Dev

如何通过SSH连接通过远程服务器连接到Internet

来自分类Dev

使用“连接到服务器”通过SFTP连接以访问远程服务器中的文件夹

来自分类Dev

连接到Mysql服务器时出现问题

Related 相关文章

  1. 1

    WebRTC处于连接状态

  2. 2

    如何在服务器仍处于活动状态时检查浏览器连接?

  3. 3

    与远程Redis服务器连接的问题

  4. 4

    iOS冰上的WebRTC冰连接状态卡住

  5. 5

    WebRTC冰候选人

  6. 6

    无法连接到服务器(通过远程连接)

  7. 7

    英特尔WebRTC 2.1.1服务器连接问题

  8. 8

    连接到远程服务器并执行简单的数据库查询时出现问题

  9. 9

    通过LAN IP地址连接WebSocket服务器

  10. 10

    通过OpenVPN连接到服务器LAN

  11. 11

    通过SSH连接LAN HTTP服务器

  12. 12

    如何通过R连接到远程服务器?

  13. 13

    从Windows通过X服务器远程连接到RHEL

  14. 14

    使用JAVA通过FTP连接到远程服务器

  15. 15

    从PHP页面连接远程服务器时出错

  16. 16

    Cake PHP:由于浏览器缓存而引起的问题,站点在我的本地系统中正常运行,但是当移至远程服务器时却无法运行

  17. 17

    如何在服务器仍处于活动状态的情况下检查浏览器连接?

  18. 18

    在WSL 2上通过Docker连接到TCP服务器时出现问题

  19. 19

    Regd:通过ODAC连接Oracle服务器时的性能问题

  20. 20

    通过VPN连接时,FTP服务器连接被拒绝

  21. 21

    我尝试连接到服务器时出现“远程服务器超时”异常

  22. 22

    在18.04.3上的〜120,000处于活动状态后,服务器停止接受连接

  23. 23

    从远程服务器上的本地服务器执行IMPDP命令时出现问题

  24. 24

    通过ssh连接到远程服务器时,以Vi模式运行zsh(oh-my-zsh)

  25. 25

    System.Net.WebException:无法连接到远程服务器-仅LAN中的服务器

  26. 26

    如何通过SSH连接通过远程服务器连接到Internet

  27. 27

    如何通过SSH连接通过远程服务器连接到Internet

  28. 28

    使用“连接到服务器”通过SFTP连接以访问远程服务器中的文件夹

  29. 29

    连接到Mysql服务器时出现问题

热门标签

归档