webrtc在服务器端通信协议,WebRtc与信令服务器通信的流程分析

webrtc

WebRTC,即Web Real-Time Communication,web实时通信技术。简单地说就是在web浏览器里面引入实时通信,包括音视频通话等。WebRTC实现了基于网页的语音对话或视频通话,目的是无插件实现web端的实时通信的能力。WebRTC提供了视频会议的核心技术,包括音视频的采集、编解码、网络传输、展示等功能,并且还支持跨平台,包括linux、windows、mac、android等。

Demo

经过大量的收集后在github上发现了这个项目

,下载运行并进行分析,虽然在很多地方存在不足,但是基本能实现通信的过程,所以就以本demo进行简要分析,过程弄清除了可以完全自己再重新写一个完整的

注意:本demo下需要自己配置node.js服务器进行验证,在本地搭建的时候需要将项目中的信令服务器地址修改为本机的ip地址

流程分析

注意:demo中分客户端 ClientA 和ClientB(本demo是通过循环一一建立连接,如下描述的单个建立连接的过程)

1.ClientA当点击进入的时候会将房间的id传递给信令服务器

sendMessage("createAndJoinRoom",message);

2.信令服务器收到消息后会回调到接口里面,此接口为:createdListener

返回的参数有:

socket id(用于建立webrtc连接用的标志)

room id (房间id)

peer (其他客户端的数据)

3.在接口中拿到信令服务器返回的东西后开始遍历peers,如果这个时候集合为空表示自己是房间的创造者,并且处于等到状态,如果集合不为空则开始遍历这个集合并与他们一一建立通过方法getOrCreateRtcConnect进行webrtc连接(建立连接是通过服务器返回的SocketId来进行连接的)并且一一给他们发送offer

for (int i = 0; i < peers.length(); i++) {

JSONObject otherPeer = peers.getJSONObject(i);

String otherSocketId = otherPeer.getString("id");

//创建WebRtcPeerConnection

Peer pc = getOrCreateRtcConnect(otherSocketId);

//通过getOrCreateRtcConnect建立的连接后再通过pc.getPc().addTrack(localVideoTrack)设置视频流!并将这个链接保存起来

//创建offer

pc.getPc().createOffer(pc,sdpMediaConstraints);

}

4.offer的创建成功会回调到下面这个方法里面:

onCreateSuccess(SessionDescription sdp)

这个时候在回调方法里面通过前面的roomid socketid等等信息创建sdp信息并再次发送给信令服务器,让信令服务器把这些消息传递给对方

具体流程如下:

调用PeerConnection的CreateOffer方法创建一个用于offer的SDP对象,SDP对象中保存当前音视频的相关参数。a通过PeerConnection的SetLocalDescription方法将该SDP对象保存起来并且构建信息再此发送给信令服务器,这个时候发送了offer

//设置本地LocalDescription

pc.setLocalDescription(Peer.this, sdp);

//构建信令数据

try {

JSONObject message = new JSONObject();

message.put("from",webRtcClient.getSocketId());

message.put("to",id);

message.put("room",webRtcClient.getRoomId());

message.put("sdp",sdp.description);

//向信令服务器发送信令

webRtcClient.sendMessage(type,message);

5.当信令服务器接受到上面发送过来的offer的时候再回调offerListener,其他客户端一一接收到ClientA发送过的offer SDP对象,通过PeerConnection的SetRemoteDescription方法将其保存起来,这时再设置自己的视频流,并调用PeerConnection的CreateAnswer方法创建一个应答的SDP对象answer,通过PeerConnection的SetLocalDescription的方法保存该 Answer SDP对象并将它通过信令服务器发。

//获取id

String fromId = data.getString("from");

//获取peer

Peer pc = getOrCreateRtcConnect(fromId);

//构建RTCSessionDescription参数

SessionDescription sdp = new SessionDescription(

SessionDescription.Type.fromCanonicalForm("offer"),

data.getString("sdp")

);

//设置远端setRemoteDescription

pc.getPc().setRemoteDescription(pc,sdp);

//设置answer

pc.getPc().createAnswer(pc,sdpMediaConstraints);

6.当信令服务器再次接受到信息时候会回调answerListener,a接收到发送过来的应答SDP对象,将其通过PeerConnection的SetRemoteDescription方法保存起来

//获取id

String fromId = data.getString("from");

//获取peer

Peer pc = getOrCreateRtcConnect(fromId);

//构建RTCSessionDescription参数

SessionDescription sdp = new SessionDescription(

SessionDescription.Type.fromCanonicalForm("answer"),

data.getString("sdp")

);

//设置远端setRemoteDescription

pc.getPc().setRemoteDescription(pc,sdp);

7.在SDP信息的offer/answer流程中,ClientA和ClientB已经根据SDP信息创建好相应的音频Channel和视频Channel并开启Candidate数据的收集,Candidate数据可以简单地理解成Client端的IP地址信息(本地IP地址、公网IP地址、Relay服务端分配的地址)

8.这个时候ClientA和ClientB开始使用穿透技术获取自己的公网地址等等信息,各自获取到后会回调到方法onIceCandidate里面并通过webRtcClient.sendMessage("candidate",message)方法将ip等信息发送给信令服务器

//新ice地址被找到触发

@Override

public void onIceCandidate(IceCandidate iceCandidate) {

Log.d(TAG,"onIceCandidate "+iceCandidate.sdpMid);

try {

//构建信令数据

JSONObject message = new JSONObject();

message.put("from",webRtcClient.getSocketId());

message.put("to",id);

message.put("room",webRtcClient.getRoomId());

//candidate参数

JSONObject candidate = new JSONObject();

candidate.put("sdpMid",iceCandidate.sdpMid);

candidate.put("sdpMLineIndex",iceCandidate.sdpMLineIndex);

candidate.put("sdp",iceCandidate.sdp);

message.put("candidate",candidate);

//向信令服务器发送信令

webRtcClient.sendMessage("candidate",message);

} catch (JSONException e) {

e.printStackTrace();

}

}

9.信令服务器接受到后会回调到接口candidateListener

//获取id

String fromId = data.getString("from");

//获取peer

Peer pc = getOrCreateRtcConnect(fromId);

//获取candidate

JSONObject candidate = data.getJSONObject("candidate");

IceCandidate iceCandidate = new IceCandidate(

candidate.getString("sdpMid"), //描述协议id

candidate.getInt("sdpMLineIndex"),//描述协议的行索引

candidate.getString("sdp")//描述协议

);

//添加远端设备路由描述

pc.getPc().addIceCandidate(iceCandidate);

10.这样ClientA和ClientB就已经建立了音视频传输的P2P通道,ClientB接收到ClientA传送过来的音视频流,会通过PeerConnection的OnAddStream回调接口返回一个标识ClientA端音视频流的MediaStream对象,在ClientB端渲染出来即可。同样操作也适应ClientB到ClientA的音视频流的传输,本demo使用onTrack回调代替了这个渲染的过程

public interface RtcListener {

//远程音视频流加入 Peer通道

void onAddRemoteStream(String peerId,VideoTrack videoTrack);

//远程音视频流移除 Peer通道销毁

void onRemoveRemoteStream(String peerId);

}

//用这个方法代替了OnAddStream方法进行了视频流的渲染

@Override

public void onTrack(RtpTransceiver transceiver) {

MediaStreamTrack track = transceiver.getReceiver().track();

Log.d(TAG,"onTrack "+ track.id());

if (track instanceof VideoTrack) {

webRtcClient.getRtcListener().onAddRemoteStream(id,(VideoTrack)track);

}

}

总结

感谢作者提供本demo进行分析,webrtc开源项目比较庞大,编译时间很长,希望通过本简要分析能明白其中通信的原理方便自己后续开发!如有疑惑之处望交流

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值