WebRTC 数据通道(RTCDataChannel)

作者:追风剑情 发布于:2024-2-27 14:50 分类:Unity3d

RTCDataChannel接口表示两个对等方之间的双向数据通道。每个数据通道都关联个RTCPeerConnection对等连接,每个对等连接理论上最多可以有65534个数据通道。RTCDataChannel接口定义如下面的代码清单所示。

//RTCDataChannel接口定义
[Exposed=window]
interface RTCDataChannel : EventTarget {
	readonly attribute USVString label;
	readonly attribute boolean ordered;
	readonly attribute unsigned short? maxPacketLifeTime;
	readonly attribute unsigned short? maxRetransmits;
	readonly attribute USVString protocol;
	readonly attribute boolean negotiated;
	readonly attribute unsigned short? id;
	readonly attribute RTCDataChannelState readyState;
	readonly attribute unsigned long bufferedAmount;
	[EnforceRange] attribute unsigned long bufferedAmountLowThreshold;
	attribute EventHandler onopen;
	attribute EventHandler onbufferedamountlow;
	attribute EventHandler onerror;
	attribute EventHandler onclosing;
	attribute EventHandler onclose;
	void close();
	attribute EventHandler onmessage;
	attribute DOMString binaryType;
	void send(USVString data);
	void send(Blob data);
	void send(ArrayBuffer data);
	void send(ArrayBufferView data);
};  

1.属性

RTCDataChannel的属性说明如下表所示。

RTCDataChannel 的属性说明
属性 类型 说明
label 字符串 只读属性,通道名称
ordered 布尔 只读属性,是否保持发包顺序
maxPacketLifeTime 数值 只读属性,发送消息间隔的最大毫秒数
maxRetransmits 数值 只读属性,发送消息失败后的重传次数
protocol 字符串 只读属性,数据通道使用的子协议名称
negotiated 布尔 只读属性,带内协商还是带外协商
id 数值 只读属性,数据通道的唯一标识
readyState RTCDataChannelState 只读属性,数据通道的状态
bufferedAmount 数值 只读属性,等待发送的缓存队列长度,单位是字节
bufferedAmountLowThreshold 数值 可读写,用于设置低位缓存的阈值,当缓存队列减少到该阈值时,触发事件 bufferedamountlow。
该属性的初始值是0,应用程序可以随时改变该属性值
binaryType 字符串 可读写,用于控制如何发送二进制数据,可设置为blob或arraybuffer

readyState 属性表示当前数据通道的状态,是 RTCDataChannelState 枚举类型,定义如下面的代码清单所示。

//RTCDataChannelState的定义
enum RTCDataChannelstate {
	"connecting",
	"open",
	"closing",
	"closed"
};  

RTCDataChannelState 包含如下枚举值。

  • connecting: 正在尝试建立数据传输通道,这是 RTCDataChannel 对象的初始状态。
  • open: 数据传输通道已建立,可以正常通信。
  • closing: 正在关闭数据传输通道。
  • closed: 数据传输通道已关闭,或者建立失败。

2.方法

(1)close() 方法

该方法用于关闭数据传输通道,每一个对等方都可以调用该方法关闭数据通道。关闭连接是异步进行的,通过监听 close 事件可以获取关闭完成的通知。

调用该方法将触发以下动作。

  • RTCDataChannel.readyState 设置为 closing。
  • close()方法调用返回,同时启动后台任务继续执行下面的任务。
  • 传输层对未完成发送的数据进行处理,协议层决定继续发送还是丢弃。
  • 关闭底层传输通道。
  • RTCDataChannel.readyState 变为 closed。
  • 如果底层传输通道关闭失败,触发NetworkError事件。
  • 如果成功,则触发close事件。
//close()方法示例
const pc = new RTCPeerConnection();
const dc = pc.createDataChannel("my channel");
dc.onmessage = (event) => {
	console.log("received:"+ event.data);
	dc.close();
};

dc.onopen = () => {
	console.log("datachannel open");
};

dc.onclose = () => {
	console.log("datachannel close");
};

(2)send() 方法

该方法通过数据通道将数据发送到对等端,调用语法如下。

RTCDataChannel.send(data);

参数:data,要发送的数据,类型可以是字符串、Blob、ArrayBuffer 或 ArrayBufferView。发送数据的大小受 RTCSctpTransport.maxMessageSize 的限制。
返回值:无。
异常值:如果该方法调用失败,返回异常值如下表所示。

send()方法异常值
异常值 说明
InvalidStateError 当前数据通道不是 open 状态
TypeError 发送数据的大小超出了 maxMessageSize
OperationError 当前缓存队列满了

//send()方法示例
const pc = new RTCPeerConnection(options);
const channel = pc.createDataChannel("chat");
channel.onopen= (event) => {
	let obj = {
		"message" : msg,
		"timestamp" : new Date()
	};
	channel.send(JSON.stringify(obj));
}

事件

(1)bufferedamountlow 事件

当缓存队列字节数从高于 bufferedAmountLowThreshold 降低到 bufferedAmountLowThreshold 之下时触发 bufferedamountlow 事件,对应事件句柄 onbufferedamountlow,事件类型为 Event。

通常情况下,当数据通道的缓存队列字节数低于设定值时,意味着数据正常发送,没有堆积,这时候可以继续向缓存队列追加数据。下面的代码清单演示了这个过程。

//onbufferedamountlow事件句柄示例
let pc = new RTCPeerConnection();
let dc = pc.createDataChannel("SendFile");
let source = /* source data object */

dc.bufferedAmountLowThreshold = 65536;
pc.onbufferedamountlow = ev => {
	if (source.position <= source.length) {
		dc.send(source.readFile(65536));
	}
};

(2)close 事件

当数据通道被关闭时触发 close 事件,对应事件句柄 onclose,事件类型为 Event。close() 方法执行了关闭的动作,关闭过程是异步的,可在 close 事件中获取事件结果。

(3)error 事件

当数据通道出现错误时,触发error事件,对应事件柄onerror,事件类型为 RTCErrorEvent。

//onerror事件句柄示例
dc.onerror = ev => {
	const err = ev.error;
	console.error("WebRTC error: ", err.message);
	switch(err.errorDetail) {
		case ""sdp-syntax-error":
			console.error("SDP syntax error in line ", err.sdpLineNumber);
			break;
		case "idp-load-failure":
			console.error(" Identity provider load failure: HTTP error ", err.httpRequestStatusCode);
			break;
		case "sctp-failure":
			console.error(" SCTP failure: ", err.sctpCauseCode);
			break;
		case "dtls-failure":
			if (err.receivedAlert) {
				console.error(" Received DLTS failure alert: ", err.receivedAlert);
			}
			if (err.sentAlert) {
				console.error(" Sent DLTS failure alert: ", err.sendAlert);
			}
			break;
	}
	console.error(" Error in file ", err.filename, " at line ", err.lineNumber, ", column ", err.columnNumber);
}

(4)message 事件

当从对等端收到消息时,触发message事件,对应事件柄onmessage。事件类型为MessageEvent,它代表目标对象收到的消息事件,也用于WebSocket的消息事件中。MessageEvent的定义如下面的代码清单所示。

//MessageEvent的定义
interface MessageEvent : Event {
	constructor(DOMString type, optional MessageEventInit eventInitDict = {});
	
	readonly attribute any data;
	readonly attribute USVString origin;
	readonly attribute DOMString lastEventId;
	readonly attribute MessageEventSource? source;
	readonly attribute FrozenArray<MessagePort> ports;
	
	void initMessageEvent(DOMString type, optional boolean bubbles = false,
		optional boolean cancelable = false, optional any data = null, optional
		USVString origin = "", optional DOMString lastEventId = "", optional
		MessageEventSource? source = null, optional sequence<Messageport> ports = []);
};

dictionary MessageEventInit : EventInit {
	any data = null;
	USVString origin = "";
	DOMString lastEventId = "";
	MessageEventSource? source = null;
	sequence<MessagePort> ports = [];
};

由于我们只需要使用 MessageEvent 的属性,所以只对属性进行说明。

MessageEvent的属性说明
属性 类型 说明
data 任意 接收到的数据,可以为任意类型
origin 字符串 描述消息发送源
lastEventId 字符串 代表当前事件的ID
source MessageEventSource 消息发送源对象
ports MessagePort[] 发送消息使用的端口

data属性代表接收到的数据,是message事件必须要使用的属性。下面的代码清单演示了onmessage事件句柄的使用方法,该示例将接收到的消息展示到页面中。

//onmessage事件句柄示例
dc.onmessage = ev => {
	let newParagraph = document.createElement("p");
	let textNode = document.createTextNode(event.data);
	newParagraph.appendChild(textNode);
	
	document.body.appendChild(newParagraph);
}

(5)open 事件

当用于收发数据的底层传输通道被打开且可用时,触发open事件,对应事件句柄onopen,事件类型为Event。

标签: Unity3d

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号