使用WebRTC搭建前端视频聊天室——点对点通信篇

使用WebRTC搭建前端视频聊天室——点对点通信篇,第1张

WebRTC给我们带来了浏览器中的视频、音频聊天体验。但个人认为,它最实用的特性莫过于DataChannel——在浏览器之间建立一个点对点的数据通道。在DataChannel之前,浏览器到浏览器的数据传递通常是这样一个流程:浏览器1发送数据给服务器,服务器处理,服务器再转发给浏览器2。这三个过程都会带来相应的消耗,占用服务器带宽不说,还减缓了消息从发送到接收的时间。其实最理想的方式就是浏览器1直接与浏览2进行通信,服务器不需要参与其中。WebRTC DataChannel就提供了这样一种方式。

如果对WebRTC和DataChannel不太了解的同学,可以先阅读如下文章:

- WebRTC的RTCDataChannel

- 使用WebRTC搭建前端视频聊天室——信令篇

- 使用WebRTC搭建前端视频聊天室——入门篇

当然服务器完全不参与其中,显然是不可能的,用户需要通过服务器上存储的信息,才能确定需要和谁建立连接。这里通过一个故事来讲述建立连接的过程:

不如钓鱼去

一些背景:

现在,老刘听说老姚钓鱼技术高超,想和老姚讨论钓鱼技巧。只要老刘和老姚相互之间知道对方的门牌号以及凭证,就可以串门了:

老刘和老姚相互之间知道了对方的门牌号和小区出入凭证,他们相互之间有什么需要交流的直接串门就行了,消息不再需要门卫老大爷来代为传达了

换个角度

我们把角色做一个映射:

于是乎故事就变成了这样:

这样,就建立了一个点对点的信道,流程如下所示:

故事

老刘和老姚已经可以相互串门了,经过一段时间的交流感情越来越深。老姚的亲友送了20斤葡萄给老姚,老姚决定送10斤给老刘。老姚毕竟年事已高,不可能一次带10斤。于是乎,老姚将葡萄分成了10份,每次去老刘家串门就送一份过去。

这里可以做如下类比:

这其实就是通过datachannel传输文件的方式,首先将文件分片,然后逐个发送,最后再统一的进行组合成一个新的文件

分片

通过HTML5的File API可以将type为file的input选中的文件读取出来,并转换成data url字符串。这也就为我们提供了很方便的分片方式:

组合

通过datachannel发送的分片数据,我们需要将其进行组合,由于是data url字符串,在接收到所有包之后进行拼接就可以了。拼接完成后就得到了一个文件完整的data url字符串,那么我们如何将这个字符串转换成文件呢?

方案一:直接跳转下载

既然是个dataurl,我们直接将其赋值给windowlocationhref自然可以下载,但是这样下载是没法设定下载后的文件名的,这想一想都蛋疼

方案二:通过a标签下载

这个原理和跳转下载类似,都是使用dataurl本身的特性,通过创建一个a标签,将dataurl字符串赋值给href属性,然后使用download确定下载后的文件名,就可以完成下载了。但是很快又有新问题了,稍微大一点的文件下载的时候页面崩溃了。这是因为dataurl有大小限制

方案三:blob

其实可以通过给a标签创建blob url的方式来进行下载,这个没有大小限制。但是我们手上是dataurl,所以需要先进行转换:

获得blob后,我们就可以通过URL API来下载了:

这里有几个点:

1 datachannel其实是可以直接传送blob的,但是只有ff支持,所以传data url

2 chrome下载是直接触发的,不会进行询问,firefox会先询问后下载,在询问过程中如果执行了revokeObjectURL,下载就会取消,囧

升级

如我们所知,WebRTC最有特点的地方其实是可以传输getUserMedia获得的视频、音频流,来实现视频聊天。但事实上我们的使用习惯来看,一般人不会一开始就打开视频聊天,而且视频聊天时很消耗内存的(32位机上一个连接至少20M左右好像,也有可能有出入)。所以常见的需求是,先建立一个包含datachannel的连接用于传输数据,然后在需要时升级成可以传输视频、音频。

看看我们之前传输的session description,它其实来自Session Description Protocol。可以看到wiki上的介绍:

这意味着什么呢?我们之前建立datachannel是没有加视频、音频流的,而这个流的描述是写在SDP里面的。现在我们需要传输视频、音频,就需要添加这些描述。所以就得重新获得SDP,然后构建offer和answer再传输一次。传输的流程和之前一样,没什么区别。但这一次,我们不需要传输任何的ice candidate,这里我曾经遇到了坑,经过国外大大的点拨才明白过来。

Peertc

我将datachannel和websocket组合,实现了一个构建点对点连接的库Peertc,它提供非常简洁的方式来建立连接和发送数据、文件和视频/音频流,详情见github。走过路过的记得star一下哦,有什么bug也非常希望能够提出来。

最后

WebRTC的点对点方式能够运用在很多场景:

- 如web qq这种Web IM工具,这就不说了

- 如象棋这种双人对战 游戏 ,每一步的数据服务器时不关心的,所以完全可以点对点发送

- 一对一在线面试、在线教育,这其实是即时通信的一个业务方向

如下:
该软件采用P2P方式,各个客户端之间直接发消息进行会话聊天,服务器在其中只扮演协调者的角色(混合型P2P)。
1会话流程设计
当一个新用户通过自己的客户端登陆系统后,从服务器获取当前在线的用户信息列表,列表信息包括了系统中每个用户的地址。用户就可以开始独立工作,自主地向其他用户发送消息,而不经过服务器。每当有新用户加入或在线用户退出时,服务器都会及时发消息通知系统中的所有其他用户,以便它们实时地更新用户信息列表。
按照上述思路,设计系统会话流程如下:
(1)用户通过客户端进入系统,向服务器发出消息,请求登陆。
(2)服务器收到请求后,向客户端返回应答消息,表示同意接受该用户加入,并顺带将自己服务线程所在的监听端口号告诉用户。
(3)客户端按照服务器应答中给出的端口号与服务器建立稳定的连接。
(4)服务器通过该连接将当前在线用户的列表信息传给新加入的客户端。
(5)客户端获得了在线用户列表,就可以独立自主地与在线的其他用户通信了。
(6)当用户退出系统时要及时地通知服务器。
2用户管理
系统中,无论是服务器还是客户端都保存一份在线用户列表,客户端的用户表在一开始登陆时从服务器索取获得。在程序运行的过程中,服务器负责实时地将系统内用户的变动情况及时地通知在线的每个成员用户。
新用户登录时,服务器将用户表传给他,同时向系统内每个成员广播“login”消息,各成员收到后更新自己的用户表。
同样,在有用户退出系统时,服务器也会及时地将这一消息传给各个用户,当然这也就要求每个用户在自己想要退出之前,必须要先告诉服务器。
3协议设计
31客户端与服务器会话
(1)登陆过程。
客户端用匿名UDP向服务器发送消息:
login,username,localIPEndPoint
消息内容包括3个字段,各字段之间用“,”分隔:“login”表示请求登陆;“username”为用户名;“localIPEndPoint”是客户端本地地址。
服务器收到后以匿名UDP返回如下消息:
Accept,port
其中,“Accept”表示服务器接受了请求;“port”是服务所在端口,服务线程在这个端口上监听可能的客户连接,该连接使用同步的TCP。
连上服务器,获取用户列表:
客户端从上一会话的“port”字段的值服务所在端口,于是向端口发起TCP连接,向服务器索取在线的用户列表,服务器接受连接后将用户列别传输给客户端。
用户列表格式如下:
username1,IPEndPoint1;username2,IPEndPoint2;;end
username1,username2为用户名,IPEndPoint1,IPEndPoint2为它们对应的端点。每个用户的信息都有个“用户名+端点”组成,用户信息之间以“;”隔开,整个用户列表以“end”结尾。
31服务器协调管理用户
(1)新用户加入通知。
由于系统中已存在的每个用户都有一份当前用户表,因此当有新成员加入时,服务器无需重复给系统中的每个成员再传送用户表,只要将新加入成员的信息告诉系统内的其他用户,再由他们各自更新自己的用户表就行了。
服务器向系统内用户广播发送如下消息:
端点字段写为“remoteIPEndPoint”,表示是远程某个用户终端登陆了,本地客户线程据此更新用户列表。其实,在这个过程中,服务器只是将受到的“login”消息简单地转发而已。
(2)用户退出。
与新成员加入时一样,服务器将用户退出的消息直接进行广播转发:
logout,username,remoteIPEndPoint
其中,“remoteIPEndPoint”为退出系统的远程用户终端的端点地址。
31用户终端之间聊天
用户聊天时,他们各自的客户端之间是以P2P方式工作的,彼此地位对等,独立,不与服务器发生直接联系。
4系统实现
41服务线程
系统运行后,先有服务器启动服务线程,只需单击“启动”按钮即可。
即时聊天软件可以在两名或多名用户之间传递即时消息的网络软件,大部分的即时聊天软件都可以显示联络人名单,并能显示联络人是否在线。使用者发出的每一句话都回即时显示在双方的萤幕上。

微信私密聊天暂时没有这个功能,作为一款社交软件,微信不打私密聊天概念。如果想要私密聊天,可以选用信源密信,一款安全即时通信工具。它的安全性体现方方面面,首先是可见的安全,信源密信依托于私有化部署,实现服务端-传输端-客户端全程加密,数据的访问、通讯、存储、使用和管理的五维深度防护⌄服务器不存储任何数据,这使得用户的信息从发送到接收,全周期加密不落地。此外,在私密聊天中,信源密信有各种安全功能,比如单次阅读,双向撤回,而且这个产品所的数据都做了加密,即时手机丢失了也无法解开这些数据。  

QQ聊天本身是两个客服端都在服务器上的,不论你聊天还是传输文件的“请求”,都需要经过服务中转。但是QQ的传输方式是P2P,也就是我们俗称的“点对点”,不需要中转就进行传输,也就像你所说的“两个客服端直接相连”~


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/12706048.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-27
下一篇 2023-05-27

发表评论

登录后才能评论

评论列表(0条)

保存