webrtc——web与android,android间通信

初次接触webrtc,尝试web端与android端通信,以及进一步实现android间通信


准备:在github上下载webrtc在android端的源码(另需下载node.js服务端源码,在该网站下有引导——https://github.com/pchab/AndroidRTC)

源码:projectRTC——服务端,也可作为web端  需在终端输入  node app.js(或者npm start,这种方法无法关闭,服务器始终运行)

   androidRTC——android端。其中有两个部分:app为主界面,webrtc-client为工具类module


WebRTC Android端的大体实现过程如下:

  • 连接服务器,并通过服务器打通两个客户端的网络通道
  • 从摄像头和麦克风获取媒体流 
  • 将本地媒体流通过网络通道传送给对方的客户端 
  • 渲染播放接收到的媒体流 

建立连接通道:
WebRTC是基于P2P的,但在连接通道建立好之前,仍需要服务器帮助传递信令,而且需要服务器帮助进行网络穿透

信令交换:

建立连接通道时我们需要在WebRTC两个客户端之间进行一些信令交换,我们以A作为发起端,B作为响应端(A call B,假设服务器和A、B已经连接好,并且只提供转发功能,PeerConnection对象为pc ):

  • A向B发出一个“init”请求
  • B收到后“init”请求后,调用pc.createOffer()方法创建一个包含SDP描述符(包含媒体信息,如分辨率、编解码能力等)的offer信令。
  • offer信令创建成功后会调用SdpObserver监听中的onCreateSuccess()响应函数,在这里B会通过pc.setLocalDescription将offer信令(SDP描述符)赋给自己的PC对象,同时将offer信令发送给A 。
  • A收到B的offer信令后,利用pc.setRemoteDescription()方法将B的SDP描述赋给A的PC对象。
  • A在onCreateSuccess()监听响应函数中调用pc.setLocalDescription将answer信令(SDP描述符)赋给自己的PC对象,同时将answer信令发送给B 。
  • B收到A的answer信令后,利用pc.setRemoteDescription()方法将A的SDP描述赋给B的PC对象。

至此,A、B之间就完成里了信令交换。


通过ICE框架穿透NAT/防火墙:

(如果在局域网内,信令交换后就已经可以传递媒体流,但如果双方不在同一个局域网,就需要进行NAT/防火墙穿透,下面是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服务器地址也需要通过信令交换,同样以A、B客户端为例过程如下:

  • A、B分别创建PC实例pc(配置了穿透服务器地址) 。
  • 当网络候选可用时,PeerConnection.Observer监听会调用onIceCandidate()响应函数并提供IceCandidate(里面包含穿透所需的信息)的对象。在这里,我们可以让A、B将IceCandidate对象的内容发送给对方。
  • A、B收到对方发来的candidate信令后,利用pc.addIceCandidate()方法将穿透信息赋给各自的PeerConnection对象。

开发历程:
当把所有的背景知识,eg:peerconnection对象,信令交换,防火墙穿透等搞通透之后,开始改代码实现android端之间的通信。(android与web端直接使用源码,在android studio下编译好即可使用)
要想实现android间通信,在看了相关node.js服务端代码后,发现服务端代码基本可以不做更改,唯一需要更改的就是服务端socketHandler.js里面client.emit('id', client.id);这行代码改为io.emit('id',client.id)以实现向连接服务端的所有客户发送加上的socket的id,从而使得其他client可以通过emitter.onId实现监听并获得id,从而执行代码,发送init,开始信令交换。而在android端,需在onCallReady方法第一行加入 callerId = callId  从而将监听到id作为参数,并sendmessage到这个id对应的socket对象,从而实现android端之间的通信。


不太懂的地方:
android端:
        final Intent intent = getIntent();
        final String action = intent.getAction();


        if (Intent.ACTION_VIEW.equals(action)) {
            final List segments = intent.getData().getPathSegments();
            callerId = segments.get(0);
        }
这些代码的目的是得到我们的callerId,但是得到的callerId通过后面的onCallReady方法中法中的实现,发现其是null,既然是null完全可以不要这几行代码,不太明
白为什么。
服务端:因为第一次接触node.js 对服务端具体的实现还处于萌新状态 
       另外,在socketHandler.js里,源代码为client.emit('id',client.id)这行代码不太理解,我总以为它的意思是服务端将客户自己的id发给客户。

你可能感兴趣的:(学习)