WebRTC API 之 RTCDataChannel 您所在的位置:网站首页 东丰雪糕批发 WebRTC API 之 RTCDataChannel

WebRTC API 之 RTCDataChannel

2023-10-01 10:17| 来源: 网络整理| 查看: 265

RTCDataChannel 接口代表在两者之间建立了一个双向数据通道的连接,属于WebRTC API 中一个很重要的接口,详细属性可参考MDN介绍。

一、RTCDataChannel

简单来说,RTCDataChannel 就是在点对点连接中建立一个双向的数据通道,从而获得文本、文件等数据的点对点传输能力。它依赖于流控制传输协议(SCTP),SCTP 是一种传输协议,类似于 TCP 和 UDP,可以直接在 IP 协议之上运行。但是,在 WebRTC 的情况下,SCTP 通过安全的 DTLS 隧道进行隧道传输,该隧道本身在 UDP 之上运行。

WebRTC API 之 RTCDataChannel

这个示例在Connect之后,可以输入文本后,使用send发送到另一端。注意: 尽管参与连接的两端都在同一页面,我们将启动连接的一端称为 “local” 端,另一端称为 “remote” 端。

1.建立本地节点 localConnection = new RTCPeerConnection(); sendChannel = localConnection.createDataChannel("sendChannel"); sendChannel.onopen = handleSendChannelStatusChange; sendChannel.onclose = handleSendChannelStatusChange;

第一步是建立该连接的 “local” 端,它是发起连接请求的一方。 下一步是通过调用RTCPeerConnection.createDataChannel() 来创建 RTCDataChannel 并设置事件侦听以监视该数据通道, 从而获知该通道的打开或关闭 (即获得该对等连接的通道打开或者关闭的时机)。

请务必记住该通道的每一端都拥有自己的 RTCDataChannel 对象。

createDataChannel方法允许传入第二个参数进行不同的配置

reliable 设置消息传递是否进行担保ordered 用来设置消息的接受是否需要按照发送时的顺序maxRetransmitTime 设置消息发送失败时,多久重新发送maxRetransmits 设置消息发送失败时,最多重发次数protocol 设置强制使用其他子协议,但当用户代理不支持该协议时会报错negotiated 此选项用来设置开发人员是否有责任在两边创建数据通道,还是浏览器来自动完成这个步骤id 这个用来设置通道的唯一标识,可以在多通道时进行区分

这些配置项很多,不过大部分只在高级应用中才会使用。主要使用的配置项是reliable和 ordered,当设置为true时数据通道表现得更像TCP,设置为False时表现得更像UDP。

negotiated 为解决两边用户同步创建数据通道而设置。用来处理ondatachannel事件触发时的不同行为。默认值是false,表示浏览器会在通道另一边自动触发这个事件,告诉它这个新通道。如果设置成True,开发者需要自己在通道两边创建相同ID的数据通道。

2.建立远程节点 remoteConnection = new RTCPeerConnection(); remoteConnection.ondatachannel = receiveChannelCallback;

远程端的建立过程类似“local”端, 但它无需自己创建 RTCDataChannel , 因为我们将通过上面建立的渠道进行连接。 我们创建对 datachannel 的事件处理回调;数据通道打开时该逻辑将被执行, 该回调处理将接收到一个 RTCDataChannel 对象,此过程将在文章后面部分描述。

3.设立ICE 候选人

下一步为每个连接建立 ICE 候选侦听处理, 当连接的一方出现新的 ICE 候选时该侦听逻辑将被调用以告知连接的另一方此消息。

注意: 在现实场景,当参与连接的两节点运行于不同的上下文,建立连接的过程或稍微复杂些,每一次双方通过调用RTCPeerConnection.addIceCandidate(),提出连接方式的建议 (例如: UDP,、中继UDP 、 TCP之类的) , 双方来回往复直到达成一致。本文既然不涉及现实网络环境,因此我们假定双方接受首次连接建议。

localConnection.onicecandidate = e => !e.candidate || remoteConnection.addIceCandidate(e.candidate) .catch(handleAddCandidateError); remoteConnection.onicecandidate = e => !e.candidate || localConnection.addIceCandidate(e.candidate) .catch(handleAddCandidateError);

我们配置每个 RTCPeerConnection 对于事件 icecandidate 建立事件处理。

4.启动连接尝试

建立节点连接的最后一项是创建一个连接offer.

localConnection.createOffer() .then(offer => localConnection.setLocalDescription(offer)) .then(() => remoteConnection.setRemoteDescription(localConnection.localDescription)) .then(() => remoteConnection.createAnswer()) .then(answer => remoteConnection.setLocalDescription(answer)) .then(() => localConnection.setRemoteDescription(remoteConnection.localDescription)) .catch(handleCreateDescriptionError); 5.数据通道(data channel)的连接

RTCPeerConnection 一旦open, 事件datachannel 被发送到远端以完成打开数据通道的处理, 该事件触发 receiveChannelCallback() 方法,如下所示:

function receiveChannelCallback(event) { receiveChannel = event.channel; receiveChannel.onmessage = handleReceiveMessage; receiveChannel.onopen = handleReceiveChannelStatusChange; receiveChannel.onclose = handleReceiveChannelStatusChange; }

事件datachannel 在它的channel属性中包括了: 对代表remote节点的 channel的RTCDataChannel 的指向, 它保存了我们用以在该channel上对我们希望处理的事件建立的事件监听。 一旦侦听建立, 每当remote节点接收到数据 handleReceiveMessage() 方法将被调用, 每当通道的连接状态发生改变handleReceiveChannelStatusChange() 方法将被调用, 因此通道完全打开或者关闭时我们都可以作出相应的相应。

6.对通道状态变化的处理

local节点和remote节点采用同样的方法处理表示通道连接状态变更的事件。

当local节点遭遇open 或者 close 事件,handleSendChannelStatusChange() 方法被调用:

function handleSendChannelStatusChange(event) { if (sendChannel) { var state = sendChannel.readyState; if (state === "open") { messageInputBox.disabled = false; messageInputBox.focus(); sendButton.disabled = false; disconnectButton.disabled = false; connectButton.disabled = true; } else { messageInputBox.disabled = true; sendButton.disabled = true; connectButton.disabled = false; disconnectButton.disabled = true; } } }

如果通道状态已经变更为 “open”, 意味着我们已经完成了在两对等节点之间建立连接。 相应地用户界面根据状态更新,许用并将输入光标聚焦在text 输入框,以便用户可以立即输入要发送给对方的文本消息, 同时界面许用 “Send” 和 “Disconnect” 按钮(既然它们已经准备好了),禁用”Connect”按钮,既然在已经建立连接的情况下用不着它。

当连接状态变更为 “closed”时,界面执行相反的操作: 禁用文本输入框和 “Send” 按钮 , 许用”Connect” 按钮, 以便用户在需要时可以打开新的连接,禁用”Disconnect” 按钮,既然没有连接时用不着它。

另一方面,作为我们例子的remote 节点, 则无视这些状态改变事件, 仅仅是在控制台输出它们:

function handleReceiveChannelStatusChange(event) { if (receiveChannel) { console.log("Receive channel's status has changed to " + receiveChannel.readyState); } } 7.发送消息

当用户按下 “Send” 按钮,触发我们已建立的该按钮的 click事件处理逻辑,在处理逻辑中调用sendMessage() 方法。 该方法也足够简单:

function sendMessage() { var message = messageInputBox.value; sendChannel.send(message); messageInputBox.value = ""; messageInputBox.focus(); }

send方法可以发送String,Blob,ArrayBuffer,ArrayBufferView。

8.接收消息

当远程通道发生“message”事件时,我们的handleReceiveMessage()方法被调用来处理事件。

function handleReceiveMessage(event) { var el = document.createElement("p"); var txtNode = document.createTextNode(event.data); el.appendChild(txtNode); receiveBox.appendChild(el); }

版权声明:本文内容转自互联网,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908#qq.com 举报,一经查实,本站将立刻删除。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有