Tom*_*uer 1 webrtc rtcdatachannel
我在接收两个对等点之间的 WebRTC 数据通道消息时遇到问题。
\n\n下面是一个 MVP,其中两个对等点位于同一页面,并且信号通道被替换为纯 JavaScript 对象交换。
\n\n我不会选择使用trickle ICE,并且我知道不使用它的缺点,我不认为它会以任何方式干扰我下面的 MVP。
\n\n代码的行为完全符合预期,并且所有日志消息都会通过。唯一缺少的是用于数据通道消息处理的消息,就好像消息从未从任一对等方发送到另一方一样。这是尝试发送Test 的事件处理程序。发送方法调用失败并出现空引用错误,我无法跟踪其根本原因。
\n\n我遵循《Untangling the WebRTC Flow》来获得这个 MVP。您可以在这里实时查看它,因此您不必亲自运行它。
\n\nclass Peer {\n    constructor(name) {\n        this.name = name;\n    }\n    offer() {\n        const peerConnection = new webkitRTCPeerConnection({ iceServers: [ { url: "stun:stun.l.google.com:19302" } ] });\n        peerConnection.onnegotiationneeded = event => console.debug(this.name, "onnegotiationneeded");\n        peerConnection.onsignalingstatechange = event => console.debug(this.name, "onsignalingstatechange", peerConnection.signalingState);\n        peerConnection.onicegatheringstatechange = event => console.debug(this.name, "onicegatheringstatechange", peerConnection.iceGatheringState);\n        peerConnection.oniceconnectionstatechange = event => console.debug(this.name, "oniceconnectionstatechange", peerConnection.iceConnectionState);\n        peerConnection.onconnectionstatechange = event => console.debug(this.name, "onconnectionstatechange", peerConnection.connectionState);\n        peerConnection.ondatachannel = event => {\n        const dataChannel = event.channel;\n        dataChannel.onopen = event => {\n            console.debug(this.name, "onopen");\n            dataChannel.send("TEST");\n        };\n        dataChannel.onclose = event => console.debug(this.name, "onclose");\n        dataChannel.onerror = event => console.debug(this.name, "onerror");\n        dataChannel.onmessage = event => console.debug(this.name, "onmessage");\n        console.debug(this.name, "ondatachannelO");\n        this.dataChannel = dataChannel;\n        };\n\n        return new Promise((resolve, reject) => {\n        peerConnection.onicecandidate = event => {\n            if (!event.candidate) {\n            peerConnection.createOffer()\n                .then(offer => {\n                console.debug(this.name, "created an offer with candidates.");\n                this.peerConnection = peerConnection;\n                resolve(peerConnection.localDescription);\n                })\n                .catch(reject);\n            }\n        };\n        peerConnection.createDataChannel("datachannel");\n        peerConnection.createOffer()\n            .then(offer => {\n            console.debug(this.name, "created an offer without candidates.");\n            peerConnection.setLocalDescription(offer)\n                .then(() => {\n                console.debug(this.name, "set local description. Collecting candidates\xe2\x80\xa6");\n                })\n                .catch(reject);\n            })\n            .catch(reject);\n        });\n    }\n    answer(offer) {\n        const peerConnection = new webkitRTCPeerConnection({ iceServers: [ { url: "stun:stun.l.google.com:19302" } ] });\n        peerConnection.onnegotiationneeded = event => console.debug(this.name, "onnegotiationneeded");\n        peerConnection.onsignalingstatechange = event => console.debug(this.name, "onsignalingstatechange", peerConnection.signalingState);\n        peerConnection.onicegatheringstatechange = event => console.debug(this.name, "onicegatheringstatechange", peerConnection.iceGatheringState);\n        peerConnection.oniceconnectionstatechange = event => console.debug(this.name, "oniceconnectionstatechange", peerConnection.iceConnectionState);\n        peerConnection.onconnectionstatechange = event => console.debug(this.name, "onconnectionstatechange", peerConnection.connectionState);\n        peerConnection.ondatachannel = event => {\n        const dataChannel = event.channel;\n        dataChannel.onopen = event => {\n            console.debug(this.name, "onopen");\n            dataChannel.send("TEST");\n        };\n        dataChannel.onclose = event => console.debug(this.name, "onclose");\n        dataChannel.onerror = event => console.debug(this.name, "onerror");\n        dataChannel.onmessage = event => console.debug(this.name, "onmessage");\n        console.debug(this.name, "ondatachannelA");\n        this.dataChannel = dataChannel;\n        };\n        return new Promise((resolve, reject) => {\n        peerConnection.onicecandidate = event => {\n            if (!event.candidate) {\n            peerConnection.createAnswer()\n                .then(answer => {\n                console.debug(this.name, "created an answer with candidates.");\n                resolve(peerConnection.localDescription);\n                })\n                .catch(reject);\n            }\n        };\n        peerConnection.setRemoteDescription(offer)\n            .then(() => {\n            console.debug(this.name, "set remote description.");\n            peerConnection.createAnswer()\n                .then(answer => {\n                console.debug(this.name, "created an answer without candidates.");\n                peerConnection.setLocalDescription(answer)\n                    .then(() => {\n                    console.debug(this.name, "set local description.");\n                    })\n                    .catch(reject);\n                })\n                .catch(reject);\n            })\n            .catch(reject);\n        });\n    }\n    sealTheDeal(proffer) {\n        return new Promise((resolve, reject) => {\n        this.peerConnection.setRemoteDescription(proffer)\n            .then(() => {\n            console.debug(this.name, "set remote description.");\n            resolve();\n            })\n            .catch(console.e);\n        });\n    }\n    send() {\n        this.dataChannel.send("TEST");\n    }\n    }\n    function flow() {\n    const peerA = new Peer("Alice");\n    const peerB = new Peer("Bob");\n    peerA.offer()\n        .then(offer => {\n        console.debug("Signal transfering offer from Alice to Bob.");\n        peerB.answer(offer)\n            .then(proffer => {\n            console.debug("Signal transfering proffer from Bob to Alice.");\n            peerA.sealTheDeal(proffer)\n                .then(() => {\n                peerB.offer()\n                    .then(offer => {\n                    console.debug("Signal transfering offer from Bob to Alice.");\n                    peerA.answer(offer)\n                        .then(proffer => {\n                        console.debug("Signal transfering proffer from Alice to Bob.");\n                        peerB.sealTheDeal(proffer)\n                            .then(() => {\n                            console.debug("HYPE");\n                            peerA.send("From Alice to Bob.");\n                            peerB.send("From Bob to Alice.");\n                            })\n                            .catch(console.error);\n                        })\n                        .catch(console.error);\n                    })\n                    .catch(console.error);\n                })\n                .catch(console.error);\n            })\n            .catch(console.error);\n        })\n        .catch(console.error);\n        window.peerA = peerA;\n        window.peerB = peerB;\n    }\n    flow();\npeerConnection.ondatachannel只对应答者开火。
提供者获取数据通道如下:
this.dataChannel = peerConnection.createDataChannel("datachannel");
其他的建议:
webkitRTCPeerConnection仅适用于 Chrome/Opera。应该使用polyfill还是使用adapter.js。例子:
this.dataChannel = peerConnection.createDataChannel("datachannel");
var pc1 = new RTCPeerConnection(), pc2 = new RTCPeerConnection();
pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);
pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);
pc1.oniceconnectionstatechange = e => console.log(pc1.iceConnectionState);
pc1.onnegotiationneeded = e =>
  pc1.createOffer().then(d => pc1.setLocalDescription(d))
  .then(() => pc2.setRemoteDescription(pc1.localDescription))
  .then(() => pc2.createAnswer()).then(d => pc2.setLocalDescription(d))
  .then(() => pc1.setRemoteDescription(pc2.localDescription))
  .catch(e => console.log(e));
var dc1, dc2;
pc2.ondatachannel = e => {
  dc2 = e.channel;
  dc2.onopen = () => console.log("Chat!");
  dc2.onmessage = e => console.log("> " + e.data);
};
dc1 = pc1.createDataChannel("chat");
dc1.onopen = () => (chat.disabled = false, chat.select());
chat.onkeypress = e => {
  if (e.keyCode != 13) return;
  dc1.send(chat.value);
  chat.value = "";
};| 归档时间: | 
 | 
| 查看次数: | 2539 次 | 
| 最近记录: |