美文网首页WebRTC音视频涛锅锅的Android资料
WebRTC 实现Android点到点互连(含Demo)

WebRTC 实现Android点到点互连(含Demo)

作者: matthew_Yang | 来源:发表于2017-10-27 19:11 被阅读3344次

背景简介

WebRTC被誉为是web长期开源开发的一个新启元,是近年来web开发的最重要创新。WebRTC允许Web开发者在其web应用中添加视频聊天或者点对点数据传输,不需要复杂的代码或者昂贵的配置。目前支持Chrome、Firefox和Opera,后续会支持更多的浏览器,它有能力达到数十亿的设备。

然而,WebRTC一直被误解为仅适合于浏览器。事实上,WebRTC最重要的一个特征是允许本地和web应用间的互操作,很少有人使用到这个特性。

所以自然Android应用也可以植入WebRTC。好处是什么?简单来说就是你可以用很简洁的代码,在手机上实现点对点的视频聊天或者数据传输,点对点!点对点!点对点!重要的事情说三遍。

项目准备

信令服务器代码:https://github.com/matthewYang92/WebRtcServer(代码改自ProjectRTC

  • 安装Node.js
  • 进入项目根目录,命令行:npm install
  • 命令行:node app.js
  • 打开浏览器输入127.0.0.1:3000,见到WebRtcServer标题,服务器ready

客户端代码:https://github.com/matthewYang92/WebRtcAndroidClient(代码参考AndroidRTC项目)

  • 下载后直接AndroidStudio打开
  • WebRtcClient.java类中的mSocketAddress变量改成你服务器的ip端口3000
  • 安装后启动App,如果服务器log显示-- xxxxx joined --证明客户端已连上服务器
  • 至少两个客户端连接到服务器之后,其中一端点击init开始连接

如果你已经成功跑通了Demo,那么恭喜你已经成功了一半,接下来我们分析下实现流程。

实现流程

一、添加WebRTC库依赖

compile 'org.webrtc:google-webrtc:1.0.+'

二、初始化核心类PeerConnectionFactory

    PeerConnectionFactory.initialize(PeerConnectionFactory
            .InitializationOptions
            .builder(this)
            .createInitializationOptions());

三、创建PeerConnection对象

        peerConnection = factory.createPeerConnection(
                iceServers, //ICE服务器列表
                constraints, //MediaConstraints
                this); //Context

四、建立P2P连接通道

WebRTC是基于P2P的,但在端与端之间的连接通道还没建立起来之前,我们需要通过一个信令服务器为端与端之间传递信令建立通道。信令服务器要做的东西很简单,就是将一端的信息透传给另一端,步骤如下(以Demo为例):我们启动A端与B端,通过SocketIO连接到信令服务器,我们以A作为发送端,B为响应端。

信令交换

  1. A向服务器发出init请求
  2. 服务器将A的init请求转发给连接上服务器的其他端
  3. B收到init请求后,调用peerConnection.createOffer()方法创建一个包含SDP的offer信令
  4. offer信令创建成功后会调用SdpObserver监听中的onCreateSuccess()响应函数,在此处B通过peerConnection.setLocalDescription()方法将SDP赋予自己的PeerConnection对象,同时将offer信令发送给服务器
  5. 服务器将offer信令转发给A端
  6. A收到offer信令后,调用peerConnection.setRemoteDescription()方法将B发过来的SDP赋予自己的PeerConnection对象,并调用peerConnection.createAnswer()方法创建一个answer信令
  7. answer信令创建成功后同样会调用SdpObserver监听中的onCreateSuccess()响应函数,在此处A同样通过peerConnection.setLocalDescription方法将SDP赋予自己的PeerConnection对象,同时将answer信令发送给服务器
  8. 服务器将answer信令转发给B端
  9. B收到A的answer信令后,利用peerConnection.setRemoteDescription()方法将A发过来的SDP赋予自己的PeerConnection对象

设置Candidate

  1. PeerConnection.Observer监听会调用onIceCandidate()响应函数并提供IceCandidate对象。然后将IceCandidate对象组成candidate信令发送给服务器
  2. 服务器将candidate信令转发给连接上服务器的其他端
  3. 收到candidate信令后调用peerConnection.addIceCandidate()IceCandidate赋予自己的PeerConnection对象

至此Peer-to-Peer的连接已经建立起来了

五、使用DataChannel收发信息

  1. 初始化DataChannel对象

        /*
        DataChannel.Init 可配参数说明:
        ordered:是否保证顺序传输;
        maxRetransmitTimeMs:重传允许的最长时间;
        maxRetransmits:重传允许的最大次数;
         */
        DataChannel.Init init = new DataChannel.Init();
        dataChannel = peerConnection.createDataChannel("dataChannel", init);
    
  2. onDataChannel()回调中注册消息回调

        dataChannel.registerObserver(this);
    
  3. 发送消息

        byte[] msg = message.getBytes();
        DataChannel.Buffer buffer = new DataChannel.Buffer(
                ByteBuffer.wrap(msg),
                false);
        dataChannel.send(buffer);
    
  4. onMessage()回调收消息

        ByteBuffer data = buffer.data;
        byte[] bytes = new byte[data.capacity()];
        data.get(bytes);
        String msg = new String(bytes);
    

六、关于ICE服务

(以下内容引用自http://blog.csdn.net/youmingyu/article/details/53192714,博主的文章对我帮助良多,非常感谢)

如果在局域网内,信令交换后就已经可以传递媒体流了,但如果双方不在同一个局域网,就需要进行NAT/防火墙穿透(我是在局域网下测试的,没有穿透,但还是把这方面内容介绍下)。

WebRTC使用ICE框架来保证穿透。ICE全名叫交互式连接建立(Interactive Connectivity Establishment),一种综合性的NAT/FW穿越技术,它是一种框架,可以整合各种NAT/FW穿越技术如STUN、TURN(Traversal Using Relay NAT 中继NAT实现的穿透)。ICE会先使用STUN,尝试建立一个基于UDP的连接,如果失败了,就会去TCP(先尝试HTTP,然后尝试HTTPS),如果依旧失败ICE就会使用一个中继的TURN服务器。使用STUN服务器穿透的结构如下:

image.png

我们可以使用Google的stun服务器:stun:stun.l.google.com:19302(Google嘛,翻墙你懂得,当然如果有精力可以自己搭建一个stun服务器),那么我们怎么把这个地址告诉WebRTC呢,还记得之前的iceServers吗,就是在创建PeerConnection对象的时候需要的参数,iceServers里面存放的就是进行穿透地址变换的服务器地址,添加方法如下(保险起见可以多添加几个服务器地址,如果有的话):

        iceServers.add(new PeerConnection.IceServer("stun:stun.l.google.com:19302"));

参考

官网
Android之WebRTC介绍
WebRTC的Android2Android实现
NAT- STUN和TURN简介

相关文章

网友评论

  • 00e8f09532b4:楼主 为什么我的jion了,但是发送信令后收不到服务端的信息
  • 敲你妹:感谢,实现音视频就更好了
  • 超威蓝猫l:06-19 18:36:26.695 29990-29990/? A/DEBUG: backtrace:
    #00 pc 00000000004432c0 /data/app/yang.webrtcdataclient-1/lib/arm64/libjingle_peerconnection_so.so (Java_org_webrtc_PeerConnectionFactory_nativeCreatePeerConnection+76)
    #01 pc 00000000000dbb90 /system/lib64/libart.so (art_quick_generic_jni_trampoline+144)
    #02 pc 00000000000d2868 /system/lib64/libart.so (art_quick_invoke_static_stub+600)
    #03 pc 00000000000df2b0 /system/lib64/libart.so (_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc+252)
    #04 pc 000000000028efbc /system/lib64/libart.so (_ZN3art11interpreter34ArtInterpreterToCompiledCodeBridgeEPNS_6ThreadEPNS_9ArtMethodEPKNS_7DexFile8CodeItemEPNS_11ShadowFrameEPNS_6JValueE+312)
    #05 pc 0000000000289078 /system/lib64/libart.so (_ZN3art11interpreter6DoCallILb1ELb0EEEbPNS_9ArtMethodEPNS_6ThreadERNS_11ShadowFrameEPKNS_11InstructionEtPNS_6JValueE+444)
    #06 pc 000000000055895c /system/lib64/libart.so (MterpInvokeStaticRange+356)
    #07 pc 00000000000c5414 /system/lib64/libart.so (ExecuteMterpImpl+15380)
  • 超威蓝猫l:A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0x7f00000000 in tid 29989 (EventThread)
    06-19 18:36:26.690 29990-29990/? A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
    Build fingerprint: 'Android/msm8953_64_c350/msm8953_64_c350:7.1.2/N2G47H/server04191706:user/release-keys'
    Revision: '0'
    ABI: 'arm64'
    pid: 29579, tid: 29989, name: EventThread >>> yang.webrtcdataclient <<<
    signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x7f00000000
    x0 0000007f00000000 x1 0000007f8beeee54 x2 0000007fa8d35500 x3 0000007f8beeee58
    x4 0000007f8beeee5c x5 0000007f8df223c0 x6 0000007fa7554933 x7 0000000000000108
    x8 e74e2e0f0457ddda x9 0000000000000000 x10 0000000000430000 x11 0000000000000000
    x12 6165724365766974 x13 6f43726565506574 x14 6e6f697463656e6e x15 2e8ba2e8ba2e8ba3
    x16 0000007f8db7d274 x17 0000007fab785bb4 x18 0000007fa7558c42 x19 0000007f00000000
    x20 0000007f8df223c0 x21 0000007f8beeee5c x22 0000007f8b01ba80 x23 0000007f8beeee58
    x24 0000007f8bef64e8 x25 0000007f8beeebf8 x26 0000007f8dfb8098 x27 0000007f8dfb8000
    x28 0000007f8beeee60 x29 0000007f8beeee20 x30 0000007f8db7d2b8
    sp 0000007f8beeebc0 pc 0000007f8db7d2c0 pstate 0000000020000000
  • 超威蓝猫l:会crash jni 部分
  • 睡着的时光:这个demo音视频没有实现?
  • 青年马土豆:博主想问下,点对点通信demo里面是对所有的peer进行发送message。
    如果多个节点,不同节点之间按照需要发送和接受不同的数据,不知道博主有什么好的思路吗?
    matthew_Yang:这是业务逻辑上的问题了,用标识区分不同类型peer再分开发送数据就可以了。
  • CLBAdai:博主 问下 有没有遇到过 factory 关不上的问题 这几天快折磨疯了 nativeFreeFactory(this.nativeFactory);报错 (视频通讯实现了 ,但是最后这个出问题了在关闭的时候)。 现在只能让视频流在后台跑:dizzy_face:
    ChineseBoy:大神,请问视频通讯如何实现的
    ChineseBoy:大神,请问是否可以发送下你的demo给我?
    matthew_Yang:peerConnection.dispose();
    videoSource.dispose();
    factory.dispose();
    需要依次调用peerConnection、videoSource和factory的dispose方法喔,有漏吗?

本文标题:WebRTC 实现Android点到点互连(含Demo)

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