React native WebRTC状态检查

React native WebRTC状态检查,react-native,webrtc,React Native,Webrtc,我想在本地主机上用WebRTC连接2台设备。所有设备都无法访问internet。它们连接到同一个本地wifi 我在React原生应用程序上尝试了这个 在这种情况下,我是否需要滴入ICE候选项和添加日期?如果我理解正确,ICE候选对象是针对iceServer。但我的情况是,iceServer为空(因为我仅脱机,连接在同一本地主机wifi上): const配置={iceServers:[{url:[]}]} 因此,实际上我交换了要约和答复,但在setRemoteDescription答复之后,con

我想在本地主机上用WebRTC连接2台设备。所有设备都无法访问internet。它们连接到同一个本地wifi

我在React原生应用程序上尝试了这个

在这种情况下,我是否需要滴入ICE候选项和添加日期?如果我理解正确,ICE候选对象是针对
iceServer
。但我的情况是,
iceServer
为空(因为我仅脱机,连接在同一本地主机wifi上):

const配置={iceServers:[{url:[]}]}

因此,实际上我交换了要约和答复,但在
setRemoteDescription
答复之后,
connectionState
将继续
检查

您可以看到我的React组件:

  constructor(props) {
    super(props);
    this.pc = new RTCPeerConnection(configuration);
  }

  state = initialState;

  componentDidMount() {
    const { pc } = this;

    if (pc) {
      this.setState({
        peerCreated: true
      });
    }

    this.setConnectionState();

    pc.oniceconnectionstatechange = () => this.setConnectionState();

    pc.onaddstream = ({ stream }) => {
      if (stream) {
        this.setState({
          receiverVideoURL: stream.toURL()
        });
      }
    };

    pc.onnegotiationneeded = () => {
      if (this.state.initiator) {
        this.createOffer();
      }
    };

    pc.onicecandidate = ({ candidate }) => {
      if (candidate === null) {
        const { offer } = this.state;
        const field = !offer ? 'offer' : 'data';

        setTimeout(() => {
          alert('setTimeout started');
          this.setState({
            [field]: JSON.stringify(pc.localDescription)
          });
        }, 2000);
      }
    };
  }

  @autobind
  setConnectionState() {
    this.setState({
      connectionState: this.pc.iceConnectionState
    });
  }

  getUserMedia() {
    MediaStreamTrack.getSources(() => {
      getUserMedia(
        {
          audio: false,
          video: true
        },
        this.getUserMediaSuccess,
        this.getUserMediaError
      );
    });
  }

  @autobind
  async getUserMediaSuccess(stream) {
    const { pc } = this;

    pc.addStream(stream);

    await this.setState({ videoURL: stream.toURL() });

    if (this.state.initiator) {
      return this.createOffer();
    }

    return this.createAnswer();
  }

  getUserMediaError(error) {
    console.log(error);
  }

  @autobind
  logError(error) {
    const errorArray = [...this.state.error, error];
    return this.setState({
      error: errorArray
    });
  }

  /**
   * Create offer
   *
   * @memberof HomeScreen
   */
  @autobind
  createOffer() {
    const { pc } = this;

    pc.createOffer()
      .then(offer => pc.setLocalDescription(offer))
      .then(() => {
        this.setState({
          offerCreated: true
        });
      })
      .catch(this.logError);
  }

  /**
   * Create anwser
   *
   * @memberof HomeScreen
   */
  @autobind
  async createAnswer() {
    const { pc } = this;
    const { data } = this.state;

    if (data) {
      const sd = new RTCSessionDescription(JSON.parse(data));

      await this.setState({
        offerImported: true
      });

      pc.setRemoteDescription(sd)
        .then(() => pc.createAnswer())
        .then(answer => pc.setLocalDescription(answer))
        .then(() => {
          this.setState({
            answerCreated: true
          });
        })
        .catch(this.logError);
    }
  }

  @autobind
  receiveAnswer() {
    const { pc } = this;
    const { data } = this.state;
    const sd = new RTCSessionDescription(JSON.parse(data));

    return pc
      .setRemoteDescription(sd)
      .then(() => {
        this.setState({
          answerImported: true
        });
      })
      .catch(this.logError);
  }

  /**
   * Start communication
   *
   * @param {boolean} [initiator=true]
   * @returns
   * @memberof HomeScreen
   */
  @autobind
  async start(initiator = true) {
    if (!initiator) {
      await this.setState({
        initiator: false
      });
    }

    return this.getUserMedia();
  }

有人可以帮我吗?

没有
ICEServer
在局域网上是可以的,但是对等方仍然必须交换至少一个候选主机:他们的主机候选主机(基于他们机器的局域网IP地址)

要么:

  • 像往常一样使用onicecandidate
  • ->信令->
    addIceCandidate
    滴流候选项,或

  • 在交换
    pc.localDescription
    之前,请等待ICE过程(几秒钟)

  • 看起来你在尝试后者。这种方法之所以有效,是因为

    涓流冰是一种优化。 使用
    onicecandidate
    的单个ice候选信令(滴流)是一种旨在加快协商的优化。一旦
    setLocalDescription
    成功,浏览器的内部ICE代理将启动,在发现候选ICE时将其插入
    localDescription
    本身。等待几秒钟进行谈判,滴水不漏是完全没有必要的:所有的ICE候选人都将在报价和答案中传输

    你的代码 从您的
    onicecandidate
    代码中,您似乎已经在尝试收集ICE完成后的
    localDescription
    (并且您已经编写完成,从两端开始工作):

    在报价方,您已正确注释掉
    createOffer
    中的等效代码:

    pc.createOffer()
      .then(offer => pc.setLocalDescription(offer))
      .catch(this.logError);
    // .then(() => {
    //   this.setState({
    //     offer: JSON.stringify(pc.localDescription)
    //   });
    // });
    
    但在回答者方面,你没有,这可能是问题所在:

    createAnswer() {
        const { pc } = this;
        const { data } = this.state;
    
        if (data) {
          const sd = new RTCSessionDescription(JSON.parse(data));
    
          pc.setRemoteDescription(sd)
            .then(() => pc.createAnswer())
            .then(answer => pc.setLocalDescription(answer))
            .then(() => {
              this.setState({
                offer: JSON.stringify(pc.localDescription)
              });
            })
            .catch(this.logError);
        }
      }
    
    这意味着,在回答者的ICE代理有时间在答案中插入任何候选人之前,它会立即发回答案。这可能就是它失败的原因


    附带说明:似乎没有什么东西等待
    getUserMedia
    完成,因此答案可能也不会包含任何视频,这取决于
    getUserMediaSuccess
    函数的计时,该函数无法向连接添加任何曲目或流。但假设您只是在做数据通道,这应该与我推荐的修复程序配合使用。

    Hi jib!谢谢你的好帖子。我已经尝试了您推荐的修复程序,但我得到了相同的结果,启动器将继续检查状态。我已经编辑了我的第一篇文章。我注意到状态应答方从未改变:始终保持在
    new
    ,可能是问题吗?我继续我的测试。我发现,在应答端导入报价后,
    pc.signalingState
    从“稳定”变为
    have remote offer
    ,持续1秒,然后回到“稳定”。我不知道问题是来自报价还是答案的生成:/手机在同一个wifi连接共享上:/这对于
    信号状态来说很正常。
    。Arf,我想问题就在那里^^也许我的剪切粘贴演示会有所帮助。
    createAnswer() {
        const { pc } = this;
        const { data } = this.state;
    
        if (data) {
          const sd = new RTCSessionDescription(JSON.parse(data));
    
          pc.setRemoteDescription(sd)
            .then(() => pc.createAnswer())
            .then(answer => pc.setLocalDescription(answer))
            .then(() => {
              this.setState({
                offer: JSON.stringify(pc.localDescription)
              });
            })
            .catch(this.logError);
        }
      }