WebRTC 笔记

最近研究了一下 WebRTC,写篇笔记记录下。

0. WebRTC 简介

WebRTC 是一种 p2p 技术,它可以在两个不同的浏览器之间建立直连,让它们互相传输数据、视频和音频流。

这个技术可以充分利用用户自己的上行带宽和网络环境,降低中心服务器的负载,既提升用户体验,又能降低服务提供者的成本。用在一些低成本的场景非常合适,比如视频会议、轻型联网游戏、内容共享网络等。

由于其低成本的优势,我想用它给 mywordle.org 升级,支持用户 1v1 对战。将来的话,还可以搞一些 FC 模拟器玩玩。

1. WebRTC 基本概念

WebRTC 的概念不少,初次连接也很复杂,有些我现在还没完全搞清楚。所以这个部分以后再慢慢更新。另外这里的内容并不是按着规范走的,而是来自我的实践。

1.1 基本概念

1.1.1 信令服务器

这可能是 WebRTC 里最重要的一个概念,每个浏览器 tab 页都是网络中的一个孤岛,必须通过信令服务器才能找到对方,建立连接。

信令服务器是必须的,不能通过人工方式完成两个节点的互联(或者说很难)。但是信令服务器并不一定要自己建,有不少公共的可以蹭。

1.1.2 Ice 服务器 RTCIceServer

同一个局域网内连接很简单,但实际上并不常见。我们日常使用的网络,无论移动网络还是家里的宽带,其实都是位于 NAT 后面,相当于总机分机的概念。两个 NAT 后面的应用想连接就比较困难了,此时就需要 RTCIceServer 帮忙,协商在两个 NAT 上打洞。

具体的实现逻辑我们不用关心,只要会用就行。目前有两类 RTCIceServer:STUN 和 TURN。前者只负责给双方牵线搭桥,本身不介入连接,有很多公共服务可以蹭;TURN 不光能把两个端连接起来,还能在两端中间网络不通的时候作为 fallback 方案。功能更强,真正生产级别的产品都需要;但是相应的,TURN 需要更高的资源支撑,免费资源也很少。

1.2 发起连接

当用户 A 想要跟用户 B 建立 WebRTC 连接时:

  1. A 创建一个 RTCPeerConnectioin 对象
  2. 创建一个 offer,其中包含着 A 的网络信息,其它人通过这个信息可能找到 A
  3. A 把 offer 发给信令服务器
  4. 信令服务器把 offer 发给用户 B
  5. 用户 B 记录下 offer,然后生成 answeransweroffer 其实是一样的,只是用来作为响应。这也是必须有信令服务器的原因。
  6. B 把 answer 发给信令服务器
  7. 信令服务器把 answer 发给 A
  8. A 尝试用 answer 建立连接,如果是局域网,双方可能已经连上了
  9. 如果连不上,则 A 尝试通过 ice server 连接。
  10. A 创建自己的 icecandidate 信息,然后发给信令服务器
  11. 信令服务器将 A 的 icecandidate 发给 B
  12. B 添加后,也创建自己的 icecandidate,发给信令服务器
  13. 信令服务器将 B 的 icecandidate 发给 A
  14. A 添加之,并尝试创建连接
  15. 如果一切正常,这个时候就连上了。

2. 实操

我建立了一个项目:meathill/webrtc-playground: learn webrtc (github.com),目前还在升级开发中。

  1. 实现一个 websocket 服务器(基于 socket.io),作为信令服务器,交换信令
  2. 用各种姿势尝试建立连接
  3. 同浏览器多 tab 连接成功
  4. 内网连接成功
  5. 手机开热点,尝试公网连接,也成功
  6. 尝试跟朋友连接,失败。遇到两个问题:
    1. 他家的网络是广州联通,我家是广州电信
    2. 他的手机网络是北京联通
    3. 目前的信令服务器会无条件广播各种信息,当我跟他都多开 tab 的时候,很难保证连接的两端是匹配的
  7. 于是接下来要重构。

3. 总结

这次学习过程一波三折。首先,WebRTC 的用户大部分关注音视频传输,毕竟这方面效果最明显;DataChannel 其实只算个添头,偏偏我最关注这个,所以找内容花了不少时间。

接下来,大部分范例代码都只是抄来抄去,一个 tab 内部来回连,经常会看错。另外,一些概念也不清不楚,比如 ice server,无法主动触发请求。

终于调通了内网和公网,又遇到联通电信问题……看来将来 TURN 服务器也必不可少。

如果您觉得文章内容对您有用,不妨支持我创作更多有价值的分享:


已发布

分类

,

来自

评论

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据