天天看點

《c# 實作p2p檔案分享與傳輸系統》 二、 設計 - 續(NAT穿透)

  首先要抱歉,因為這些日子較忙,沒有寫文章,這個系列拖了很久,現在開始繼續。 

  NAT(Network Address Translation, 網絡位址轉換),是指在IP包通過路由裝置時,修改其IP位址資訊的技術。一般應用是,通過将内網位址轉換為公網位址,進而實作多台主機使用一個IP位址通路網際網路,在很多網絡環境中,均可見到。這項技術的好處我們暫且不談,對我們來說它的“壞處”是顯而易見的,因為中間存在了NAT,給我們的p2p網絡中主機之間的通信造成了不小的麻煩。下面開始先簡單了解一下NAT的類型。(這裡隻做簡單介紹,針對“一對多”的NAT映射。更加詳細、嚴謹的說明,請看Wikipedia和相關文檔 - RFC xxxx。)

  一般來說,可以把它分為“對稱型NAT”和“非對稱型NAT(也叫錐形NAT)”。所謂“對稱”,是指内部位址與不同的外部位址進行通信的時候,NAT為會話綁定不同的IP和端口。

《c# 實作p2p檔案分享與傳輸系統》 二、 設計 - 續(NAT穿透)

  對于NAT可分為“不限型”、“IP受限型”和“IP-端口受限型”:

不限:内網主機Peer通過NAT通路外網Peer1:port1建立了會話,NAT為其配置設定了ip:port位址,則任何外網主機均可通過ip:port通路内網主機Peer

IP受限:内網主機Peer通過NAT與外網Peer1:port1建立了會話,NAT為其配置設定了ip:port位址,則隻有Peer1可以通過ip:port通路内網主機Peer

IP-Port受限:内網主機Peer通過NAT與外網Peer1:port1建立了會話,NAT為其配置設定了ip:port位址,則隻有Peer1,且從port1發出的會話,可以通過ip:port通路内網主機Peer

《c# 實作p2p檔案分享與傳輸系統》 二、 設計 - 續(NAT穿透)

  正确的判斷NAT類型,在p2p網絡中的NAT穿透中,是很重要的。NAT類型的判斷,是由Stun Server來實作,據我所知,有現成的,也有開源項目,這裡将不做介紹~

  通過以上NAT的特點可知,為了能通路位于受限NAT後面的内網主機Peer,必須讓該内網主機先主動向自己發送會話。但是,如何通知内網主機來做這件事呢?這就需要借助NAT Server來實作。NAT Server需要保持可以随時向Peer發送指令的能力,首先就是NAT Server必須位于公網(-_-!),Peer定時向NAT Server發送心跳包。由之前的分析可知,NAT Server可以無障礙的向Peer發送各種指令。如果你對發送心跳包的間隔拿捏不定,不妨設定為10秒。

  下面是NAT Server的基本流程

《c# 實作p2p檔案分享與傳輸系統》 二、 設計 - 續(NAT穿透)

  1) 外網主機向NAT Server發送打洞請求

  2) NAT Server向Peer發送打洞指令

  3) Peer向外網主機發送連接配接封包

  4) NAT為外網主機打開了通路内網Peer的權限,打洞完成。

  根據以上的打洞技術,可以在多種NAT情況下實作穿透,但對于部分情況,例如,兩個用戶端都處于受限型NAT後面,而其中又至少有一個處于對稱型NAT後面,這種技術就無能為力了,此時可以采用“位址-端口預測”的方法(據說迅雷使用了這項技術,據說而已),所謂“端口預測”,是猜測NAT給内網主機配置設定位址和端口的算法,比如這篇文章的第一幅圖裡,ip1:port1和ip2:port2,ip1和ip2,port1和port2很可能在數值上相差不遠,比如可能是61.22.3.1:13304, 61.22.3.1:13305,這時,通過多發幾個端口,就有可能實作打通。實在不行,就隻能通過伺服器中轉了。下面羅列一下在各種NAT情況之下,實作Peer和Peer1之間互聯的方法:

  我們把情況假設在p2p網絡中,Peer1向Peer索取資料

  

《c# 實作p2p檔案分享與傳輸系統》 二、 設計 - 續(NAT穿透)
《c# 實作p2p檔案分享與傳輸系統》 二、 設計 - 續(NAT穿透)

文章版權所有,如需轉載,請注明作者和出處,謝謝~