本文詳細描述了基於STUN系列協議實現的P2P SIP電話過程,其中涉及到了SIP信令的交互,P2P的原理,以及STUN、TURN、ICE的協議交互
本文所提到的各個服務單元的交互均使用UDP,不涉及TCP的打洞及其他和TCP相關的操作。
本文假設通信雙方均沒有防火牆對協議以及端口的限制。
本文不涉及客戶端的資源的發布與查找。
本文適用於有一定基礎的讀者,比如說知道NAT設備的不同類型及其特點、知道STUN/TURN/ICE協議的基本概念、知道SIP協議的相關交互流程等。
本文力求嚴謹,但難免有疏漏之處,敬請諒解,歡迎批評指正。
本文大致可分為4個部分:
第一部分,解釋了穿越和打洞的概念以及STUN系列協議穿越的特點
第二部分,STUN、TURN協議的工作原理及其作用,詳細介紹了relay端口的分配、消息的接受與發送、STUN頭的添加與去除
第三部分,ICE協議的工作原理及其作用,詳細介紹了ICE的打洞原理、兩種打洞模式、Peer Reflexive的概念與發現過程
第四部分,ICE在P2P SIP中的應用,詳細講解了SIP的信令交互流程與媒體建立流程。
有人將穿越打洞認為是一個概念,其實這也無傷大雅,在與其他人交流討論的時候不產生歧義就好。嚴格來說,是先打洞,後穿越。
由於NAT的特性(請查閱NAT的幾種不同類型的各自特點),一個位於外界的主機是不可能向內網主機直接建立連接的。要想實現外界主機與內網主機的交互,那麼 “我(內部主機)在我自己的NAT設備上先打一個洞,然後使得你(外界主機)的數據能經過這個洞穿越過來”。
當我們打開電腦,連上網絡,打開幾個不同網站的時候,打洞和穿越時時刻刻都在發生著。你打開www.sina.com的時候,你就在自己的NAT上打了一個洞,這個洞只允許www.sina.com的80端口的數據穿越回來。如果沒有你先打的洞,sina是不可能成功給你發消息的。
時刻記住一個概念,打洞是為了能讓對方的數據過來。
既然打洞和穿越實時都在發生著,那麼在client/server模型的網絡編程中為什麼很少提及打洞和穿越的概念,卻在P2P通信中反復提及呢?
首先,在cs模型的網絡編程中,服務器都架設在公網,服務器端不用打洞(服務端不用為客戶端打洞,客戶端的數據也能過來),客戶端就能向服務器發送請求。
其次,client向服務器發送請求時,client的打洞和服務器響應的穿越是自動實現的。
最後,明確一點的是,cs模型中,打洞是單方向的,即只需客戶端打洞。
而在P2P網絡編程中,通信的雙方A和B既要當服務器,又要當客戶端。因此打洞是雙方的:A在自己的NAT上為B打一個洞,讓B的數據能過來;B在自己的NAT上為A打一個洞,讓A的數據能過來;
AB雙方的打洞的操作得由我們自己完成,所以不得不提及穿越打洞的概念。
理解了“P2P通信中,打洞是雙方的”這一點,也就理解了ICE的一半。
在知道NAT的幾種類型和每種類型的限制後,就是針對性的解決這些問題實現NAT的穿越。
最容易想到的就是,能不能在NAT上做一下手腳,讓它能識別出我特有的協議,從而不限制我特有的協議,這就是ALG的初衷。ALG(應用層網關),有兩個功能,一個是修改自己“認識的”協議中相關字段的內網地址為外網地址;另一個是,允許自己“認識的”協議直接穿透,而不需要打洞;
可以認為ALG的能力是NAT的一個插件,插上什麼協議類型的插件,NAT就能辨別什麼類型的協議,繼而對相應類型的協議做相關操作。常用的應用有FTP、DNS、ICMP、SIP等。在VOIP中,如果使用ALG的話,可以實現通信雙方的直接媒體通信,但是不足之處就是需要NAT支持SIP,這就不適合像skype類型的應用。
還有一種成熟的穿越技術:UPnP,它的想法跟ALG有點類似,也是在NAT上做了手腳。當內網的主機啟動UPnP程序的時候,就會在NAT上產生 “映射端口”與UPnP程序的端口一一映射,而且不會被回收。從外部來的消息,只要是發送到“映射端口”的,直接就會送至內網的UPnP程序。像我們平常用到的迅雷、電騾等,這種方式也不用打洞,但缺點就是需要應用程序、操作系統以及NAT支持UPnP,同樣不適用於skype類型的應用。
使用STUN/TURN/ICE最大的好處充分利用NAT的特性,不需要操作系統支持、不需要對現有的NAT設備做改變就能實現穿越。
最後需要說明的一點就是,沒有不好的技術,只有不適合的技術。
簡單來說,STUN的目的是為了進行P2P通信,通過提供反射地址(Server Reflexive Address)這種能力來使雙方可以進行P2P通信,但是依賴NAT類型的不同,這種方式是有失敗的概率的:比如雙方都為對稱型NAT或者一方為對稱型,另一方為端口限制型。
因為有失敗的可能性,所以單純的依賴STUN協議提供的反射地址的話,需要事先探測出雙方的NAT類型,假如發現是對稱型的NAT,那麼就不打洞了,而是直接中轉。目前網絡類型紛繁復雜,STUN協議在5389的時候去掉了NAT類型的判斷的能力,因為越來越多的實踐發現,在多層NAT下,類型的探測不總是有效的。而使用ICE的時候,不需要事先探測NAT類型。
STUN還有一個作用是為ICE提供支持(對Binding的擴展)。
TURN協議的目的是為了保證通信雙方百分之百能進行通信,就是在只知道反射地址而打洞失敗的情況下的一種補充方案-----使用中繼,使用中繼方式百分之百能使得雙方進行通信,只不過已經不是P2P的了,而且伴隨而來的是轉發效率的問題。不過這不要緊,因為該協議的目的就是保證雙方肯定能通信,損失效率來保證了連同性。
ICE協議的目的就是綜合以上兩種方案,通過通信雙方互相發探測包,找出一種最合理,最廉價的可行路徑。ICE首先探測內網地址,再探測STUN提供的反射地址,最後探測TURN協議的中繼地址,反正最終目的就是探出一條路,內網地址不行用反射地址,反射地址不行,最後不得已情況下那就用中繼地址。
一般來說,目前的TURN服務器通常也實現了STUN協議,所以可以稱之為TURN服務器或者是STUN 服務器。
如果說一個服務器是STUN服務器,那麼該服務器可能是純的STUN(RFC 5389)服務器,也可能是一個TURN(RFC 5766)服務器,也可能是兩者都實現了的服務器。本文以下圖中所說的STUN服務器,均為實現了STUN和TURN的服務器。
未完。。。。待續。。。。
本文為原創,轉載請注明一下內容:
名稱:STUN/TURN/ICE協議在P2P SIP中的應用(一)
作者:大雪先生
鏈接:http://www.cnblogs.com/ishang/p/3810382.html