作為WebRTC的三大模塊之一,DataChannel支持短消息(short message)二進(jìn)制和文本數(shù)據(jù)的傳輸,因此伟阔,對(duì)于通常以傳輸音視頻為主的WebRTC來(lái)說(shuō)搭综,當(dāng)需要傳輸音視頻以外的數(shù)據(jù)的時(shí)候就有很大用處了。
這樣聽起來(lái)站辉,DataChannel
看起來(lái)和Websocket
實(shí)現(xiàn)的功能很相似呢撞。的確,DataChannel模型最初是基于webSocket建立的饰剥,具有簡(jiǎn)單可設(shè)置的send方法和onMessage方法殊霞。但是它們之間的區(qū)別是很明顯的:
1、RTCDataChannel通信是在peer與peer之間直接連接汰蓉,所以RTCDataChannel比WebSocket更快绷蹲,因?yàn)閃ebSocket需要服務(wù)器中轉(zhuǎn);但是相應(yīng)的顾孽,WebRTC依靠ICE Servers來(lái)穿透NAT祝钢,有的場(chǎng)景下可能會(huì)多一層TURN服務(wù)器的轉(zhuǎn)發(fā)。
2若厚、WebSocket協(xié)議是基于TCP傳輸?shù)睦褂ⅲ軌虮WC數(shù)據(jù)的安全有序地到達(dá);而RTCDataChannel是基于SCTP傳輸協(xié)議(SCTP是一種TCP盹沈、UDP同級(jí)的傳輸協(xié)議)龄章, 默認(rèn)情況下是可靠有序傳輸吃谣。但是它也可以配置是否進(jìn)行可靠的傳輸,這就意味著有可能會(huì)通過(guò)丟失數(shù)據(jù)來(lái)達(dá)到性能的要求做裙,這使得RTCDataChannel更為靈活岗憋。這里說(shuō)一下,為什么會(huì)有配置不可靠傳輸?shù)男枨竽孛恳驗(yàn)閷?shí)時(shí)通信對(duì)時(shí)間是非常敏感的仔戈,以音視頻為例,它可以容忍間接性的數(shù)據(jù)包丟失拧廊,可以通過(guò)算法來(lái)填補(bǔ)這個(gè)丟失的數(shù)據(jù)监徘,因此WebRTC對(duì)及時(shí)性和低延時(shí)的要求要比數(shù)據(jù)傳輸?shù)目煽啃砸蟾摺?br>
3、WebSocket構(gòu)造需要一個(gè)url吧碾,與服務(wù)器建立連接凰盔,創(chuàng)建一個(gè)唯一的SocketSessionId;DataChannel 的連接依賴于一個(gè)RTCPeerConnection對(duì)象倦春,當(dāng)RTCPeerConnection建立起來(lái)后户敬,可以包含一個(gè)或多個(gè)RTCDataChannel。
還有其他的一些區(qū)別睁本,例如大文件傳輸時(shí)的擁塞控制尿庐、加密等,不在列舉呢堰。
在IOS WebRTC中抄瑟,要使用RTCDataChannel非常簡(jiǎn)單
#import <WebRTC/RTCDataChannel.h>
#import <WebRTC/RTCDataChannelConfiguration.h>
- (void)createDataChannelWithPeerConnection:(RTCPeerConnection*)peerConnection connectionId:(NSString*)connectionId{
//給p2p連接創(chuàng)建dataChannel
RTCDataChannelConfiguration *dataChannelConfiguration = [[RTCDataChannelConfiguration alloc] init];
dataChannelConfiguration.isNegotiated = NO;
RTCDataChannel* localDataChannel = [peerConnection dataChannelForLabel:@"localDataChannel" configuration:dataChannelConfiguration];
localDataChannel.delegate = self;
[self.localDataChannelDictionary setObject:localDataChannel forKey:connectionId];//本地記錄一下
}
有一點(diǎn)很重要,就是DataChannel的創(chuàng)建是在生成本地offer之前枉疼,這樣才能在生成offer后皮假,使offer中包含DataChannel的信息。
關(guān)于DataChannel的配置參數(shù)往衷,你可以查看<WebRTC/RTCDataChannelConfiguration.h>
中的各種參數(shù)及說(shuō)明钞翔。
當(dāng)創(chuàng)建好RTCDataChannel后,下面的回調(diào)會(huì)被執(zhí)行:
/** New data channel has been opened. */
- (void)peerConnection:(RTCPeerConnection*)peerConnection didOpenDataChannel:(RTCDataChannel*)dataChannel{
NSLog(@"%s",__func__);
dataChannel.delegate = self;
}
不要忽略設(shè)置delegate = self哦席舍,否則你是無(wú)法收發(fā)消息的布轿。
發(fā)送消息:
-(void)sendMessage:(NSString *)message{
NSDictionary* messageDic = @{@"type":@"text",@"value":message};
NSData* messageData = [NSJSONSerialization dataWithJSONObject:messageDic options:NSJSONWritingPrettyPrinted error:nil];
RTCDataBuffer *buffer = [[RTCDataBuffer alloc] initWithData:messageData isBinary:NO];
[self.localDataChannelDictionary enumerateKeysAndObjectsUsingBlock:^(NSString* connectionId, RTCDataChannel* dataChannel, BOOL * _Nonnull stop) {
bool success = [dataChannel sendData:buffer];
if (success){
NSLog(@"sendmessageSuccess = %@",message);
}else{
NSLog(@"SendMessageFailed");
}
}];
}
這里需要說(shuō)一下,如果使用RTCDataChannel發(fā)送圖片来颤,需要將type設(shè)置為image汰扭,并且進(jìn)行base64編碼。
當(dāng)收到消息時(shí)福铅,下面的回調(diào)會(huì)被執(zhí)行:
/** The data channel successfully received a data buffer. */
- (void)dataChannel:(RTCDataChannel *)dataChannel didReceiveMessageWithBuffer:(RTCDataBuffer *)buffer{