已建立WebRTC数据通道连接但未发送消息

时间:2016-10-23 15:18:27

标签: webrtc rtcdatachannel

我无法在两个对等方之间接收WebRTC数据通道消息。

下面是一个MVP,其中两个对等体是同一页面,信令通道被替换为纯JavaScript对象交换。

我不选择使用涓流ICE而且我知道不使用它的缺点,我不相信它会以任何方式干扰我的MVP。

代码的行为完全符合预期,所有日志消息都会通过。唯一缺少的是用于数据通道消息处理的消息,就好像消息从来没有来自任何一个对等点。这与尝试发送 Test 的事件处理程序有关。 send 方法调用失败,出现空引用错误,我无法跟踪其根本原因。

我已经跟随Untangling the WebRTC Flow来了解我对这个MVP的看法。 You can see it live here so you don't have to run it yourself.

class Peer {
    constructor(name) {
        this.name = name;
    }
    offer() {
        const peerConnection = new webkitRTCPeerConnection({ iceServers: [ { url: "stun:stun.l.google.com:19302" } ] });
        peerConnection.onnegotiationneeded = event => console.debug(this.name, "onnegotiationneeded");
        peerConnection.onsignalingstatechange = event => console.debug(this.name, "onsignalingstatechange", peerConnection.signalingState);
        peerConnection.onicegatheringstatechange = event => console.debug(this.name, "onicegatheringstatechange", peerConnection.iceGatheringState);
        peerConnection.oniceconnectionstatechange = event => console.debug(this.name, "oniceconnectionstatechange", peerConnection.iceConnectionState);
        peerConnection.onconnectionstatechange = event => console.debug(this.name, "onconnectionstatechange", peerConnection.connectionState);
        peerConnection.ondatachannel = event => {
        const dataChannel = event.channel;
        dataChannel.onopen = event => {
            console.debug(this.name, "onopen");
            dataChannel.send("TEST");
        };
        dataChannel.onclose = event => console.debug(this.name, "onclose");
        dataChannel.onerror = event => console.debug(this.name, "onerror");
        dataChannel.onmessage = event => console.debug(this.name, "onmessage");
        console.debug(this.name, "ondatachannelO");
        this.dataChannel = dataChannel;
        };

        return new Promise((resolve, reject) => {
        peerConnection.onicecandidate = event => {
            if (!event.candidate) {
            peerConnection.createOffer()
                .then(offer => {
                console.debug(this.name, "created an offer with candidates.");
                this.peerConnection = peerConnection;
                resolve(peerConnection.localDescription);
                })
                .catch(reject);
            }
        };
        peerConnection.createDataChannel("datachannel");
        peerConnection.createOffer()
            .then(offer => {
            console.debug(this.name, "created an offer without candidates.");
            peerConnection.setLocalDescription(offer)
                .then(() => {
                console.debug(this.name, "set local description. Collecting candidates…");
                })
                .catch(reject);
            })
            .catch(reject);
        });
    }
    answer(offer) {
        const peerConnection = new webkitRTCPeerConnection({ iceServers: [ { url: "stun:stun.l.google.com:19302" } ] });
        peerConnection.onnegotiationneeded = event => console.debug(this.name, "onnegotiationneeded");
        peerConnection.onsignalingstatechange = event => console.debug(this.name, "onsignalingstatechange", peerConnection.signalingState);
        peerConnection.onicegatheringstatechange = event => console.debug(this.name, "onicegatheringstatechange", peerConnection.iceGatheringState);
        peerConnection.oniceconnectionstatechange = event => console.debug(this.name, "oniceconnectionstatechange", peerConnection.iceConnectionState);
        peerConnection.onconnectionstatechange = event => console.debug(this.name, "onconnectionstatechange", peerConnection.connectionState);
        peerConnection.ondatachannel = event => {
        const dataChannel = event.channel;
        dataChannel.onopen = event => {
            console.debug(this.name, "onopen");
            dataChannel.send("TEST");
        };
        dataChannel.onclose = event => console.debug(this.name, "onclose");
        dataChannel.onerror = event => console.debug(this.name, "onerror");
        dataChannel.onmessage = event => console.debug(this.name, "onmessage");
        console.debug(this.name, "ondatachannelA");
        this.dataChannel = dataChannel;
        };
        return new Promise((resolve, reject) => {
        peerConnection.onicecandidate = event => {
            if (!event.candidate) {
            peerConnection.createAnswer()
                .then(answer => {
                console.debug(this.name, "created an answer with candidates.");
                resolve(peerConnection.localDescription);
                })
                .catch(reject);
            }
        };
        peerConnection.setRemoteDescription(offer)
            .then(() => {
            console.debug(this.name, "set remote description.");
            peerConnection.createAnswer()
                .then(answer => {
                console.debug(this.name, "created an answer without candidates.");
                peerConnection.setLocalDescription(answer)
                    .then(() => {
                    console.debug(this.name, "set local description.");
                    })
                    .catch(reject);
                })
                .catch(reject);
            })
            .catch(reject);
        });
    }
    sealTheDeal(proffer) {
        return new Promise((resolve, reject) => {
        this.peerConnection.setRemoteDescription(proffer)
            .then(() => {
            console.debug(this.name, "set remote description.");
            resolve();
            })
            .catch(console.e);
        });
    }
    send() {
        this.dataChannel.send("TEST");
    }
    }
    function flow() {
    const peerA = new Peer("Alice");
    const peerB = new Peer("Bob");
    peerA.offer()
        .then(offer => {
        console.debug("Signal transfering offer from Alice to Bob.");
        peerB.answer(offer)
            .then(proffer => {
            console.debug("Signal transfering proffer from Bob to Alice.");
            peerA.sealTheDeal(proffer)
                .then(() => {
                peerB.offer()
                    .then(offer => {
                    console.debug("Signal transfering offer from Bob to Alice.");
                    peerA.answer(offer)
                        .then(proffer => {
                        console.debug("Signal transfering proffer from Alice to Bob.");
                        peerB.sealTheDeal(proffer)
                            .then(() => {
                            console.debug("HYPE");
                            peerA.send("From Alice to Bob.");
                            peerB.send("From Bob to Alice.");
                            })
                            .catch(console.error);
                        })
                        .catch(console.error);
                    })
                    .catch(console.error);
                })
                .catch(console.error);
            })
            .catch(console.error);
        })
        .catch(console.error);
        window.peerA = peerA;
        window.peerB = peerB;
    }
    flow();

1 个答案:

答案 0 :(得分:1)

peerConnection.ondatachannel只会对回答者开火。

提供者获得如下数据通道:

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 = "";
};

Chat: <input id="chat" disabled></input>
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>
&#13;
&#13;
&#13;