1

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

下面是一个 MVP,其中两个对等点都是同一个页面,信号通道被普通的 JavaScript 对象交换所取代。

我不会选择使用涓流 ICE,并且我知道不使用它的缺点,我认为它不会以任何方式干扰我下面的 MVP。

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

我已经按照Untangling the WebRTC Flow来了解我在这个 MVP 中的位置。你可以在这里看到它,所以你不必自己运行它。

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();
4

1 回答 1

4

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>

于 2016-10-24T03:54:17.690 回答