WebRTC 允许浏览器以前无法做到的事情,但各种不熟悉的术语和 API 的复杂性造成了陡峭的学习曲线。在花了几个星期深入研究示例代码和模仿几个库之后,我获得了一个可行的理解,并开发了一个巧妙的库,它有助于隐藏 WebRTC 在其最简单的两个方向的点对点通信用例中的复杂性。
但在开始谈论 库 之前,了解它所抽象的部分有助于理解。
爱丽丝和鲍勃(以及 ICE、NAT、STUN 和 SDP)
当两个设备想要互相交谈时,我们需要一种方法让它们交换联系信息,比如它们的 IP 地址。与 DNS 服务器帮助浏览器定位远程机器的方式类似,我们可以设置一个共同知道的服务器来帮助潜在的同行定位彼此。在 WebRTC 中,这被称为信令服务器。
在我们的简单用例中,每个对等方都与信令服务器联系。服务器为对等方提供彼此的地址,然后对等方可以开始交换数据。
情节变得复杂
如今的互联网并非完全如此。大多数在线计算机没有唯一的 IP 地址;它们与本地网络上的所有其他设备共享一个公共地址。大多数本地网络也拥有防火墙来保护机器免受不需要的入站流量。交换 IP 地址是不够的。
用 ICE 治愈伤口
电信行业已经解决这个问题有一段时间了*。连接可以通过防火墙和路由器返回到内部网络的方式有很多。 ICE 是一个包含所有内容的协议,它使用经过验证的技术“尝试一切并查看哪些有效™”。一个称为 STUN 服务器的服务器使用 ICE 协议来找出并告知对等方从公共互联网可以访问它的所有方式。这些潜在的连接方法被称为ICE 候选。
当机器收到候选时,它需要将其传达给它的对等方。在这里,信令服务器再次发挥作用——将每个对等方的候选传递给另一个对等方。
调用和响应
当设备想要建立连接时,它会生成一条名为offer 的消息并使用信令服务器将其发送给对等方。该 offer 以 SDP 格式编码,包含有关该设备的信息——例如,它知道如何使用哪些协议以及它拥有的哪些通信方法。当远程对等方收到 offer 时,它会以其自身的 SDP 消息(称为answer)进行响应。然后,两个潜在的对等方互相发送可能的 ICE 候选。一旦对等方找到对他们都有效的连接方法,连接就会建立起来!
让我们从头开始
让我们回顾一下连接过程,结合上面所有技术
- 设备使用信令服务器将 SDP offer 传递给潜在的对等方。同时,它要求 ICE 服务器找出从公共互联网如何访问它。
- 潜在的对等方用其自己的连接 offer 进行回复,并收集 ICE 候选。
- 对等方使用信令服务器交换 ICE 候选,尝试使用它们来打开连接。
- 一旦每个对等方找到有效的候选,连接就会建立起来。
让我们给他们一些用来交谈的东西
一旦建立了 PeerConnection,它就可以用于传输音频和视频 MediaStreams 以及更通用的 DataChannel。人们对浏览器之间的视频会议感到兴奋(有充分的理由!),但 WebRTC 不仅仅是关于语音和视频。RTCDataChannel
提供了一个与 WebSocket 类似的通用数据管道。它功能强大且实用,但推广不足。
处理繁琐代码
WebRTC 是一个低级、底层的 API。它由多个小型、可组合的 API 组成,这些 API 提供了大量的灵活性,以及 可扩展性。这样做的缺点是,即使完成一项基本任务也可能需要大量的样板代码。想法是 JS 库和框架将介入来抽象掉这种复杂性,实际上,已经存在大量 WebRTC 库。
其中许多库由于缺乏信令服务器和对没有 WebRTC 支持的浏览器的回退支持而达不到预期。为了解决这个问题,Chris Van 和我共同构建了 SocketPeer。
使用 SocketPeer
SocketPeer 正如其名称所暗示的那样,是 WebSockets 和 RTCPeerConnection
的结合。这个 node.js 库抽象掉了使用 WebSockets 作为信令服务器来实例化 WebRTC 上的 DataChannel 的常见模式。如果对等方无法建立点对点连接,WebSocket 服务器也将作为消息中继的回退。
服务器代码
// In your server module alongside existing application code.
var SocketPeer = require('socketpeer');
new SocketPeer();
我承认这有点简单,但 SocketPeer 的设计旨在简化运行信令服务器的过程——在最简单的情况下,它为您完成了所有工作。服务器是相当可配置的,但默认情况下,它会自行处理,方法是
- 如果未提供
http.Server
,则创建http.Server
。 - 附加逻辑来服务客户端
socketpeer.js
库。 - 如果未提供 WebSocket 服务器,则启动 WebSocket 服务器。
- 开始监听默认端口。
如果您只需要一个基本的信令服务器,那么这就是您需要的全部代码。但假设您想将 SocketPeer 集成到现有的 Express 应用程序中
// `app` is an existing Express Application
var server = http.createServer(app);
new SocketPeer({
httpServer: server
});
server.listen(/* port */);
客户端代码
如上所述,当 SocketPeer 在服务器上运行时,它将在已知 URL 上提供客户端库。默认情况下,可以在 /socketpeer/socketpeer.js
中找到它。客户端库公开了一个事件接口和一系列 事件,让您了解连接状态。三个最重要的事件是
connect
– 当对等方配对时触发。此时可以使用 WebSockets 交换数据。upgrade
– 当建立 RTCPeerConnection 时触发。现在可以使用点对点方式交换数据。data
– 当从远程对等方收到数据时触发。
最后一个重要信息称为 pairCode
。这是一个点对点连接的两端用来互相识别的任意字符串。它可以是任何双方同意的值。
var peer = new SocketPeer({
pairCode: 'foobar'
});
peer.on('connect', function () {
// connected via WebSockets
peer.send('Hello via WebSockets.');
});
peer.on('upgrade', function () {
// now using RTCPeerConnection
peer.send('Hello via WebRTC!');
});
peer.on('data', function (data) {
// do something awesome
});
聊天是新的待办事项
没有有效的演示,示例代码有什么意义?我构建了一个使用 SocketPeer 进行点对点聊天的超级简单示例。 试一试,并在 GitHub 上查看代码 了解其工作原理。
该库仍在开发中,但所有核心功能都已到位并经过测试。请尝试一下,并告知我们对 API 的任何 问题或反馈。
* 本文作者不是电信工程师。他阅读了很多维基百科文章,浏览了一些 RFC,所以你不必这样做。
2 条评论