背景简介
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为响应端。
信令交换
A向服务器发出init请求
服务器将A的init请求转发给连接上服务器的其他端
B收到init请求后,调用
peerConnection.createOffer()
方法创建一个包含SDP的offer信令offer信令创建成功后会调用
SdpObserver
监听中的onCreateSuccess()
响应函数,在此处B通过peerConnection.setLocalDescription()
方法将SDP赋予自己的PeerConnection
对象,同时将offer信令发送给服务器服务器将offer信令转发给A端
A收到offer信令后,调用
peerConnection.setRemoteDescription()
方法将B发过来的SDP赋予自己的PeerConnection
对象,并调用peerConnection.createAnswer()
方法创建一个answer信令answer信令创建成功后同样会调用
SdpObserver
监听中的onCreateSuccess()
响应函数,在此处A同样通过peerConnection.setLocalDescription
方法将SDP赋予自己的PeerConnection
对象,同时将answer信令发送给服务器服务器将answer信令转发给B端
B收到A的answer信令后,利用
peerConnection.setRemoteDescription()
方法将A发过来的SDP赋予自己的PeerConnection
对象
设置Candidate
PeerConnection.Observer
监听会调用onIceCandidate()
响应函数并提供IceCandidate
对象。然后将IceCandidate
对象组成candidate信令发送给服务器服务器将candidate信令转发给连接上服务器的其他端
收到candidate信令后调用
peerConnection.addIceCandidate()
将IceCandidate
赋予自己的PeerConnection
对象
至此Peer-to-Peer的连接已经建立起来了
五、使用DataChannel收发信息
初始化DataChannel对象
/* DataChannel.Init 可配参数说明: ordered:是否保证顺序传输; maxRetransmitTimeMs:重传允许的最长时间; maxRetransmits:重传允许的最大次数; */ DataChannel.Init init = new DataChannel.Init(); dataChannel = peerConnection.createDataChannel("dataChannel", init);
在
onDataChannel()
回调中注册消息回调dataChannel.registerObserver(this);
发送消息
byte[] msg = message.getBytes(); DataChannel.Buffer buffer = new DataChannel.Buffer( ByteBuffer.wrap(msg), false); dataChannel.send(buffer);
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简介