MQTT作为WebRTC信令

Stun Server是开源的coTurn穿透服务器,Signal Server是开源的Apache Active MQ。
部署环境 搭建信令服务器 Signal Server用的是开源的Apache ActiveMQ,网上有很多花里胡哨的方法,这个是简单能搭建成功的过程,搭建过程。
搭建穿透服务 穿透服务器用的是开源的coturn,搭建过程
SDP交换
根据MQTT协议订阅发布机制:
订阅同一个主题:(实现接收消息)
发布同一个主题:(实现发布消息)
对于每一个客户端来说唯一标示是ClientId,客户端发布消息时设置的主题也是ClientId.
1、客户端连接到ActiveMQ服务器

MQTT作为WebRTC信令
文章图片
main 这里的ClientId,就是在ActiveMQ服务端添加的

MQTT作为WebRTC信令
文章图片
添加ClientId 这里主要是连接到ActiveMQ的流程

/** * 连接到服务器 * @param clientId */ private void CreateConnect(String clientId) { this.clientId = clientId; //服务器地址 Stringuri ="tcp://"; uri = uri + host + ":" + port; Log.d(TAG,"URI === " + uri + "ClientID === " + clientId); MqttAndroidClient client = new MqttAndroidClient(context,uri,clientId); mqttConnection = new MqttConnection(clientId,host,port,client,false); MqttConnectOptions conOpt = new MqttConnectOptions(); conOpt.setConnectionTimeout(30); //连接超时时间 conOpt.setKeepAliveInterval(60); //心跳间隔时间 100 Sclient.setCallback(new MqttCallbackHandler(context,clientId)); //连接后的回调 //开始连接到服务器 try { client.connect(conOpt,null,new ConnectCallBackHandler(context)); } catch (MqttException e) { e.printStackTrace(); } }

首先,呼叫方initCall,主要作用是创建PeerConnection对象,设备,将音视频数据封装成MediaStream添加到然后打开本地音视频PeerConnection中,显示呼叫页面。
然后呼叫方startCall,主要作用是CreateOffer,SendOffer,所以要发布Topic:呼叫方Message;
假如ClientA呼叫ClientB,首先ClientA订阅主题ClientB,然后ClientB订阅主题ClientA。
【MQTT作为WebRTC信令】Client A给Client B发送消息时,发布主题Client_A_ID和Message。
Client B给Client A发送消息时,发布主题Client_B_ID和Message。
zjf001连接到服务器
根据前面文章,看一下基本流程
  • Client A连接到Signal Server,订阅所有主题,Client B连接到Signal Server,订阅所有主题。
  • Client A首先发布主题TOPIC_CLIENTIDA_TO_CLIENTIDB_CALL_OUT,发送消息CALL_OUT,创建PeerConnection对象,设备,将音视频数据封装成MediaStream添加到然后打开本地音视频PeerConnection中,显示呼叫页面。
  • Client B收到消息CALL_OUT之后,显示接听页面,点击接听按钮之后,Client B发布主题TOPIC_CLIENTIDB_TO_CLIENTIDA_CALL_IN,发送消息CALL_IN,Client A接收到CALL_IN后,ClientA调用PeerConnection的CreateOffer方法创建一个用于offer的SDP对象,SDP对象中保存当前音视频的相关参数。ClientA通过PeerConnection的SetLocalDescription方法将该SDP对象保存起来,然后发布主题TOPIC_CLIENTIDA_TO_CLIENTIDB_OFFER_SDP
    和消息SDP,并通过Signal服务器发送给ClientB。
  • ClientB接收到ClientA发送过的offer SDP对象,通过PeerConnection的SetRemoteDescription方法将其保存起来,并调用PeerConnection的CreateAnswer方法创建一个应答的SDP对象,通过PeerConnection的SetLocalDescription的方法保存该应答SDP对象,然后发布主题TOPIC_CLIENTIDB_TO_CLIENTIDA_ANSWER_SDP和消息SDP,并将它通过Signal服务器发送给ClientA。
  • ClientA接收到ClientB发送过来的应答SDP对象,将其通过PeerConnection的SetRemoteDescription方法保存起来。
  • 在SDP信息的offer/answer流程中,ClientA和ClientB已经根据SDP信息创建好相应的音频Channel和视频Channel并开启Candidate数据的收集,Candidate数据可以简单地理解成Client端的IP地址信息(本地IP地址、公网IP地址、Relay服务端分配的地址)。
  • 当ClientA收集到Candidate信息后,PeerConnection会通过OnIceCandidate接口给ClientA发送通知,ClientA会发布主题 TOPIC_CLIENTIDA_TO_CLIENTIDB_CANDIDATE
    和消息ICESERVER,ClientA将收到的Candidate信息通过Signal服务器发送给ClientB,ClientB接收到消息后,通过PeerConnection的AddIceCandidate方法保存起来。同样的操作ClientB对ClientA再来一次。
  • 这样ClientA和ClientB就已经建立了音视频传输的P2P通道,ClientB接收到ClientA传送过来的音视频流,会通过PeerConnection的OnAddStream回调接口返回一个标识ClientA端音视频流的MediaStream对象,在ClientB端渲染出来即可。同样操作也适应ClientB到ClientA的音视频流的传输。

    推荐阅读