发布网友 发布时间:2024-09-26 08:59
共1个回答
热心网友 时间:2024-10-04 14:11
WebRTC可以实现实时通信,他可以直接建立两个浏览器之间点对点的连接,在连接中实时传输媒体流和任何数据。这就非常适合进行屏幕共享。
WebRTC使用起来还是挺复杂的,具体的介绍MDN非常详细,不过网上各种,信令服务器,ICE,SDP,NAT的介绍弄得我晕头转向,所以我就找到一个简单的Demo,通过这个Demo来理解怎么使用。
一、创建RTCPeer首先我们模拟创建两个pc端。直接通过RTCPeerConnection创建就好。
//创建两个PeerConnection模拟两个客户端,pc1相当于本地,pc2相当于远端constpc1=newRTCPeerConnection();constpc2=newRTCPeerConnection();二、交换ICEWebRTC使用了ICE(交互式连接设施)的框架协议,在建立连接之前两个客户端需要互相交换,简单的说就是交换网络信息,告知两个客户端互相的地址。
//交换ICE候选//可以理解为通知pc2连接pc1的地址pc1.onicecandidate=e=>{pc2.addIceCandidate(e.candidate);};//可以理解为通知pc1接pc2地址pc2.onicecandidate=e=>{pc1.addIceCandidate(e.candidate);};三、交换SDPWebRTC使用了SDP(会话描述协议)去交换两端的媒体信息,比如说分辨率格式等信息,主要是交换双方的Offer和Answer,这两个信息叫做提议(Offer)和应答(Answer)非常的形象。
//设置offer和answer,可理解为通知两边另一边的编解码等媒体信息//1.pc1创建offerpc1.createOffer(displayMediaOptions).then(desc=>{//2.pc1设置offerpc1.setLocalDescription(desc)//3.pc2设置offerpc2.setRemoteDescription(desc)//4.pc2创建answerpc2.createAnswer().then(answerDesc=>{//5.pc2设置answerpc2.setLocalDescription(answerDesc)//6.pc1设置answerpc1.setRemoteDescription(answerDesc)})})这里双方做的事就是存下自己的信息,然后发送和接收对方的Offer或Answer。步骤如下图所示。
四、添加媒体最后还有两件简单的事情需要处理,一个是添加需要传输的媒体,还有就是监听到媒体后使用video去播放。
//将需要传输的流添加给PeerConnectionstream.getTracks().forEach(track=>pc1.addTrack(track,stream));//远端接收到流,交给video去播放pc2.ontrack=event=>{if(videoTag.srcObject!==event.streams[0]){videoTag.srcObject=event.streams[0];}};通过上面的这四个简单步骤我们实现了WebRTC最简单的一个实例。然后有的同学就会有质疑了,你这是在一个浏览器页面下进行的传输,作为端对端的传输能不能在两个页面下分别创建pc1和pc2?
五、信令服务器经过了解,WebRTC只会负责端对端的连接,中间的数据传输,控制传输给谁,和谁建立连接都是他不管的,所以需要我们自己去传输。
通过WebSocket来把pc1和pc2之间的信息传递一下。然后就有了以下伪代码。这里只演示交换ICE候选,交换SDP同理。
PC1的代码:
constpc1=newRTCPeerConnection();constsocket=你创建的socket连接//交换ICE候选pc1.onicecandidate=e=>{socket.emit('ice的信息',e.candidate)};socket.on('ice的信息',data=>{pc1.addIceCandidate(data);})PC2的代码:
constpc2=newRTCPeerConnection();constsocket=你创建的socket连接//交换ICE候选pc2.onicecandidate=e=>{socket.emit('ice的信息',e.candidate)};socket.on('ice的信息',data=>{pc2.addIceCandidate(data);})看起来很简单不过经过测试后发现连不通,打印出传输后的消息发现传输后的消息都变成了普通对象。
然而在传输前他是一个RTCIceCandidate的对象
通过查阅API我们可以在传输后实例化这个对象就可以连接了。
newRTCIceCandidate(data)下图就是我们所需要进行的所有信息的传输步骤。
其实我们WebSocket做的事情在WebRTC中被叫做信令服务器,信令就是双方发送的所有信息,你可以通过任何形式传输这些信息,WebSocket也好Http请求也可以,因为信令服务器不需要理解这些中间信息,也不需要做额外的处理,唯一要做的就是把信息带到另外一方。
六、一对多实现WebRTC只是一对一两端之间的通信,但是我们存在一对多的需求,不过这种需求量挺小的,所以我们采取了最简单的办法就是同一个客户端创建多个WebRTC。但是在业内也有更加优秀的解决方案,使用SFUServer让服务器去模拟一个客户端与每个客户端之间建立联系,帮客户端分担压力,这样就把通讯压力放在了我们可控的服务端上了。效果如下图所示。
在继续优化你可以使用MCUServer的方案,在服务器合并多路连接。
具体内容可以看这篇文章的讲解。
七、NAT穿透最后在项目提测前夕有发现一个大问题,之前开发两个浏览器端都是一台机测试,然后在两台设备上试了下发现一直连接不上,后来了解到是NAT和防火墙的原因导致双方无法通信。
WebRTC使用的ICE整合了STUN和TURN,STUN服务可以获取客户端的公网IP和端口,如果使用STUN依然无法建立连接就需要用到,TURN服务,可以中继所有的数据来绕过NAT。google提供了免费的STUN服务器,不过也可以自己搭建,搭建的话可以了解一下coturn。在WebRTC上配置对应的服务也非常简单。
constpc=newRTCPeerConnection({//可以传入多个stun服务器或者turn服务器iceServers:[{url:'stun:stun.l.google.com:19302'},{url:'stun:stun1.l.google.com:19302'}]})原文:https://juejin.cn/post/7097142990036008968