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