利用Phoenix代理进行P2P WebRTC开发

WebRTC(Web实时通信)的创建主要是为了视频和音频通信,但它也有在两个浏览器之间传递二进制数据的API。这为创建更多的点对点Web应用程序带来了许多机会,而且已经有许多有趣的应用程序是使用它创建的,如WebTorrent、UberConference。

Zohaib Rauf是一名软件工程师,他正在学习Elixir语言。为了更好地理解WebRTC,他使用它创建了一个P2P文件分享应用程序,目标是实现点对点的文件分享,而不需要任何中间人。文件发送者添加文件,并将唯一URL分享给接收者。接收者访问唯一URL就可以看到分享的文件并下载,如下图所示:

利用Phoenix代理进行P2P WebRTC开发_第1张图片

在该应用程序中,Zohaib使用Phoenix框架实现了一个用于初次握手的代理。近日,他发表了一篇博文,简要介绍了该代理的设计决策过程。

代理的作用

为了创建点对点的连接,发起者会创建一个包含其网络信息和其它媒体相关信息的握手请求。接收者在收到请求后会创建应答和它自己的申请并发送回发起者。发起者接收到应答后完成初次握手。至此,发起者和接收者就可以进行点对点通信了。在这个过程中,需要有一种方式交换握手请求信息,这就是代理的用途所在了。

代理的实现要满足如下两个要求:

  1. 它应该能够通过WebSocket使用对等节点的ID与其通信;
  2. 它需要维护已接入的对等节点的信息。

每个对等节点在接入Zohaib的Web应用时都会获得一个唯一ID,并在收到唯一ID后将自己进行注册。

使用对等节点ID进行通信

对于第一点要求,Zohaib尝试了两种方法。第一种方法是为对等节点ID和与它相关连的Socket维护一个通用的映射。当需要同某个对等节点通信时,就使用对等节点的唯一ID检索出Socket,并将消息推送给它。第二种方法是每个对等节点连接到一个唯一的主题,当需要向那个节点发送消息时,只需将消息广播到那个主题。有且只有一个对等节点会注册到那个主题,所以,其它对等节点不会获得这条消息。Zohaib采用了第二种方法,因为第一种方法需要一个Elixir代理存储映射。这样,每个通信请求都需要向该代理发送消息获取Socket,它会成为瓶颈,而且不可扩展。而在第二种方法中,当向WebSocket注册时,节点会连接到唯一的主题(比如peer:20dd48ca-fdcf-41c9-9a3b-f192f77650f9)。这时,就可以使用函数ApplicationName.Endpoint.broadcast(topic, event, payload)向该主题发送消息。

对等节点信息维护

对于第二点要求,Zohaib同样尝试了两种方法。第一种方法是同上文描述的一样,保存一个通用的映射。但当Socket连接关闭或Socket进程结束时,代理需要自己维护映射关系。第二种方法是使用Elixir/Erlang的全局名称注册功能。这种方式可以将一个全局名称注册到对应的PID。当进程崩溃或终止时,该名称会自动解除注册。而且,这种方法可以扩展到多个节点。因此,Zohaib采用了第二种方法。当节点注册时,它会启动一个简单的GenServer,后者维护与节点相关的信息,并为节点分配一个像peer_state:<UUID>这样的全局名称。该进程会链接到Socket进程,如果Socket关闭或崩溃,那么该进程也会终止并解除注册。在这种方式中,代理不需要自己维护映射。

交换WinRTC请求

有了代理,就可以交换握手请求了。例如,发送者将一个像http://epicshare.zohaib.me/?peer_id=20dd48ca-fdcf-41c9-9a3b-f192f77650f9这样URL的分享,其中包含对等节点的ID。接收者打开该URL后会获得一个唯一ID,并像上文描述的那样将自己注册到代理。那样,两个对等节点就都通过Web Socket连接到代理了。下一步,它们就可以发送和接收握手请求了,过程如下所示:

利用Phoenix代理进行P2P WebRTC开发_第2张图片

感兴趣的读者可以试用Zohaib的程序,或者下载源代码。

另外,从Hacker News网友的讨论中得知,使用WebRTC在两个浏览器之间交换请求/应答可以不借助任何服务器。

感谢魏星对本文的审校。

给InfoQ中文站投稿或者参与内容翻译工作,请邮件至[email protected]。也欢迎大家通过新浪微博(@InfoQ,@丁晓昀),微信(微信号:InfoQChina)关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入InfoQ读者交流群InfoQ好读者)。

你可能感兴趣的:(利用Phoenix代理进行P2P WebRTC开发)