首頁(yè) > 新聞 > 專家觀點(diǎn) >

利用Phoenix代理進(jìn)行P2P WebRTC開(kāi)發(fā)

2015-08-21 10:08:10   作者:   來(lái)源:InfoQ中文站   評(píng)論:0  點(diǎn)擊:


  WebRTC(Web實(shí)時(shí)通信)的創(chuàng)建主要是為了視頻和音頻通信,但它也有在兩個(gè)瀏覽器之間傳遞二進(jìn)制數(shù)據(jù)的API。這為創(chuàng)建更多的點(diǎn)對(duì)點(diǎn)Web應(yīng)用程序帶來(lái)了許多機(jī)會(huì),而且已經(jīng)有許多有趣的應(yīng)用程序是使用它創(chuàng)建的,如WebTorrent、UberConference。

  Zohaib Rauf是一名軟件工程師,他正在學(xué)習(xí)Elixir語(yǔ)言。為了更好地理解WebRTC,他使用它創(chuàng)建了一個(gè)P2P文件分享應(yīng)用程序,目標(biāo)是實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)的文件分享,而不需要任何中間人。文件發(fā)送者添加文件,并將唯一URL分享給接收者。接收者訪問(wèn)唯一URL就可以看到分享的文件并下載,如下圖所示:

  在該應(yīng)用程序中,Zohaib使用Phoenix框架實(shí)現(xiàn)了一個(gè)用于初次握手的代理。近日,他發(fā)表了一篇博文,簡(jiǎn)要介紹了該代理的設(shè)計(jì)決策過(guò)程。

  代理的作用

  為了創(chuàng)建點(diǎn)對(duì)點(diǎn)的連接,發(fā)起者會(huì)創(chuàng)建一個(gè)包含其網(wǎng)絡(luò)信息和其它媒體相關(guān)信息的握手請(qǐng)求。接收者在收到請(qǐng)求后會(huì)創(chuàng)建應(yīng)答和它自己的申請(qǐng)并發(fā)送回發(fā)起者。發(fā)起者接收到應(yīng)答后完成初次握手。至此,發(fā)起者和接收者就可以進(jìn)行點(diǎn)對(duì)點(diǎn)通信了。在這個(gè)過(guò)程中,需要有一種方式交換握手請(qǐng)求信息,這就是代理的用途所在了。

  代理的實(shí)現(xiàn)要滿足如下兩個(gè)要求:

  1.它應(yīng)該能夠通過(guò)WebSocket使用對(duì)等節(jié)點(diǎn)的ID與其通信;
  2.它需要維護(hù)已接入的對(duì)等節(jié)點(diǎn)的信息。

  每個(gè)對(duì)等節(jié)點(diǎn)在接入Zohaib的Web應(yīng)用時(shí)都會(huì)獲得一個(gè)唯一ID,并在收到唯一ID后將自己進(jìn)行注冊(cè)。

  使用對(duì)等節(jié)點(diǎn)ID進(jìn)行通信

  對(duì)于第一點(diǎn)要求,Zohaib嘗試了兩種方法。第一種方法是為對(duì)等節(jié)點(diǎn)ID和與它相關(guān)連的Socket維護(hù)一個(gè)通用的映射。當(dāng)需要同某個(gè)對(duì)等節(jié)點(diǎn)通信時(shí),就使用對(duì)等節(jié)點(diǎn)的唯一ID檢索出Socket,并將消息推送給它。第二種方法是每個(gè)對(duì)等節(jié)點(diǎn)連接到一個(gè)唯一的主題,當(dāng)需要向那個(gè)節(jié)點(diǎn)發(fā)送消息時(shí),只需將消息廣播到那個(gè)主題。有且只有一個(gè)對(duì)等節(jié)點(diǎn)會(huì)注冊(cè)到那個(gè)主題,所以,其它對(duì)等節(jié)點(diǎn)不會(huì)獲得這條消息。Zohaib采用了第二種方法,因?yàn)榈谝环N方法需要一個(gè)Elixir代理存儲(chǔ)映射。這樣,每個(gè)通信請(qǐng)求都需要向該代理發(fā)送消息獲取Socket,它會(huì)成為瓶頸,而且不可擴(kuò)展。而在第二種方法中,當(dāng)向WebSocket注冊(cè)時(shí),節(jié)點(diǎn)會(huì)連接到唯一的主題(比如peer:20dd48ca-fdcf-41c9-9a3b-f192f77650f9)。這時(shí),就可以使用函數(shù)ApplicationName.Endpoint.broadcast(topic,event,payload)向該主題發(fā)送消息。

  對(duì)等節(jié)點(diǎn)信息維護(hù)

  對(duì)于第二點(diǎn)要求,Zohaib同樣嘗試了兩種方法。第一種方法是同上文描述的一樣,保存一個(gè)通用的映射。但當(dāng)Socket連接關(guān)閉或Socket進(jìn)程結(jié)束時(shí),代理需要自己維護(hù)映射關(guān)系。第二種方法是使用Elixir/Erlang的全局名稱注冊(cè)功能。這種方式可以將一個(gè)全局名稱注冊(cè)到對(duì)應(yīng)的PID。當(dāng)進(jìn)程崩潰或終止時(shí),該名稱會(huì)自動(dòng)解除注冊(cè)。而且,這種方法可以擴(kuò)展到多個(gè)節(jié)點(diǎn)。因此,Zohaib采用了第二種方法。當(dāng)節(jié)點(diǎn)注冊(cè)時(shí),它會(huì)啟動(dòng)一個(gè)簡(jiǎn)單的GenServer,后者維護(hù)與節(jié)點(diǎn)相關(guān)的信息,并為節(jié)點(diǎn)分配一個(gè)像peer_state:<UUID>這樣的全局名稱。該進(jìn)程會(huì)鏈接到Socket進(jìn)程,如果Socket關(guān)閉或崩潰,那么該進(jìn)程也會(huì)終止并解除注冊(cè)。在這種方式中,代理不需要自己維護(hù)映射。

  交換WinRTC請(qǐng)求

  有了代理,就可以交換握手請(qǐng)求了。例如,發(fā)送者將一個(gè)像http://epicshare.zohaib.me/?peer_id=20dd48ca-fdcf-41c9-9a3b-f192f77650f9這樣URL的分享,其中包含對(duì)等節(jié)點(diǎn)的ID。接收者打開(kāi)該URL后會(huì)獲得一個(gè)唯一ID,并像上文描述的那樣將自己注冊(cè)到代理。那樣,兩個(gè)對(duì)等節(jié)點(diǎn)就都通過(guò)Web Socket連接到代理了。下一步,它們就可以發(fā)送和接收握手請(qǐng)求了,過(guò)程如下所示:

  感興趣的讀者可以試用Zohaib的程序,或者下載源代碼。

  另外,從Hacker News網(wǎng)友的討論中得知,使用WebRTC在兩個(gè)瀏覽器之間交換請(qǐng)求/應(yīng)答可以不借助任何服務(wù)器。

分享到: 收藏

專題