美文网首页audio and vidioWebRTC
iOS WebRTC 杂谈之 RTCDataChannel

iOS WebRTC 杂谈之 RTCDataChannel

作者: 王沐凡 | 来源:发表于2018-11-22 14:44 被阅读0次

    作为WebRTC的三大模块之一,DataChannel支持短消息(short message)二进制和文本数据的传输,因此,对于通常以传输音视频为主的WebRTC来说,当需要传输音视频以外的数据的时候就有很大用处了。
    这样听起来,DataChannel看起来和Websocket实现的功能很相似。的确,DataChannel模型最初是基于webSocket建立的,具有简单可设置的send方法和onMessage方法。但是它们之间的区别是很明显的:
    1、RTCDataChannel通信是在peer与peer之间直接连接,所以RTCDataChannel比WebSocket更快,因为WebSocket需要服务器中转;但是相应的,WebRTC依靠ICE Servers来穿透NAT,有的场景下可能会多一层TURN服务器的转发。
    2、WebSocket协议是基于TCP传输的,它能够保证数据的安全有序地到达;而RTCDataChannel是基于SCTP传输协议(SCTP是一种TCP、UDP同级的传输协议), 默认情况下是可靠有序传输。但是它也可以配置是否进行可靠的传输,这就意味着有可能会通过丢失数据来达到性能的要求,这使得RTCDataChannel更为灵活。这里说一下,为什么会有配置不可靠传输的需求呢?因为实时通信对时间是非常敏感的,以音视频为例,它可以容忍间接性的数据包丢失,可以通过算法来填补这个丢失的数据,因此WebRTC对及时性和低延时的要求要比数据传输的可靠性要求更高。
    3、WebSocket构造需要一个url,与服务器建立连接,创建一个唯一的SocketSessionId;DataChannel 的连接依赖于一个RTCPeerConnection对象,当RTCPeerConnection建立起来后,可以包含一个或多个RTCDataChannel。
    还有其他的一些区别,例如大文件传输时的拥塞控制、加密等,不在列举。

    在IOS WebRTC中,要使用RTCDataChannel非常简单

    #import <WebRTC/RTCDataChannel.h>
    #import <WebRTC/RTCDataChannelConfiguration.h>
    
    - (void)createDataChannelWithPeerConnection:(RTCPeerConnection*)peerConnection connectionId:(NSString*)connectionId{
        //给p2p连接创建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];//本地记录一下
    }
    

    有一点很重要,就是DataChannel的创建是在生成本地offer之前,这样才能在生成offer后,使offer中包含DataChannel的信息。
    关于DataChannel的配置参数,你可以查看<WebRTC/RTCDataChannelConfiguration.h>中的各种参数及说明。
    当创建好RTCDataChannel后,下面的回调会被执行:

    /** New data channel has been opened. */
    - (void)peerConnection:(RTCPeerConnection*)peerConnection didOpenDataChannel:(RTCDataChannel*)dataChannel{
        NSLog(@"%s",__func__);
        dataChannel.delegate = self;
    }
    

    不要忽略设置delegate = self哦,否则你是无法收发消息的。
    发送消息:

    -(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");
            }
        }];
    }
    

    这里需要说一下,如果使用RTCDataChannel发送图片,需要将type设置为image,并且进行base64编码。

    当收到消息时,下面的回调会被执行:

    /** The data channel successfully received a data buffer. */
    - (void)dataChannel:(RTCDataChannel *)dataChannel didReceiveMessageWithBuffer:(RTCDataBuffer *)buffer{
    

    相关文章

      网友评论

        本文标题:iOS WebRTC 杂谈之 RTCDataChannel

        本文链接:https://www.haomeiwen.com/subject/jjgkqqtx.html