P2P技術詳解(二):P2P中的NAT穿越(打洞)方案詳解

目錄

  • 1、內容概述
  • 2、反向鏈接技術:一種特殊的P2P場景(通信雙方中只有一方位于NAT設備之后)
  • 3、基于UDP協議的P2P打洞技術詳解
    • 3.1、原理概述
    • 3.2、典型P2P情景1: 兩客戶端位于同一NAT設備后面(即相同內網中)
    • 3.3、典型P2P情景2: 兩客戶端位于不同的NAT設備后面(分屬不同的內網)
    • 3.4、典型P2P情景3: 兩客戶端位于兩層(或多層)NAT設備之后(分屬不同的內網)
    • 3.5、一個需要考慮的現實問題:UDP在空閑狀態下的超時
  • 4、基于TCP協議的P2P打洞技術詳細
    • 4.1、套接字和TCP端口的重用
    • 4.2、打開P2P的TCP流
    • 4.3、從應用程序的角度來看TCP“打洞”
  • 5、本文小結

1、內容概述

P2P即點對點通信,或稱為對等聯網,與傳統的服務器客戶端模式(如下圖“P2P結構模型”所示)有著明顯的區別,在即時通訊方案中應用廣泛(比如IM應用中的實時音視頻通信、實時文件傳輸甚至文字聊天等)。

P2P可以是一種通信模式、一種邏輯網絡模型、一種技術、甚至一種理念。在P2P網絡中(如右圖所示),所有通信節點的地位都是對等的,每個節點都扮演著客戶機和服務器雙重角色,節點之間通過直接通信實現文件信息、處理器運算能力、存儲空間等資源的共享。P2P網絡具有分散性、可擴展性、健壯性等特點,這使得P2P技術在信息共享、即時通訊、協同工作、分布式計算、網絡存儲等領域都有廣闊的應用。

圖1 - 經典的CS模式:
在這里插入圖片描述
圖2 - P2P結構模型:
在這里插入圖片描述
NAT技術和P2P技術作為經典的兩項網絡技術,在現在的網絡上有著廣泛的應用,P2P主機位于NAT網關后面的情況屢見不鮮。NAT技術雖然在一定程度上解決了IPv4地址短缺的問題,在構建防火墻、保證網絡安全方面都發揮了一定的作用,卻破壞了端到端的網絡通信。NAT阻礙主機進行P2P通信的主要原因是NAT不允許外網主機主動訪問內網主機,但是P2P技術卻要求通信雙方都能主動發起訪問,所以要在NAT網絡環境中進行有效的P2P通信,就必須采用新的解決方案。

P2P作為一項實用的技術,有很大的優化空間,并且相對于網絡設備,基于P2P的應用程序在實現上更為靈活。所以為了兼容NAT,基于P2P的應用程序在開發的時候大多會根據自身特點加入一些穿越NAT的功能以解決上述問題。以下著重介紹幾種常見的P2P穿越NAT方案。

2、反向鏈接技術:一種特殊的P2P場景(通信雙方中只有一方位于NAT設備之后)

此種情況是所有P2P場景中最簡單的,它使用一種被稱為“反向鏈接技術”來解決這個問題。大致的原理如下所述。

如圖3所示,客戶端A位于NAT之后,它通過TCP端口1234連接到服務器的TCP端口1235上,NAT設備為這個連接重新分配了TCP端口62000。客戶端B也通過TCP端口1234連接到服務器端口1235上。A和B從服務器處獲知的對方的外網地址二元組{IP地址:端口號}分別為{138.76.29.7:1234}和{155.99.25.11:62000},它們在各自的本地端口上進行偵聽。

由于B 擁有外網IP地址,所以A要發起與B的通信,可以直接通過TCP連接到B。但如果B嘗試通過TCP連接到A進行P2P通信,則會失敗,原因是A位于NAT設備后,雖然B發出的TCP SYN請求能夠到達NAT設備的端口62000,但NAT設備會拒絕這個連接請求。要想與Client A通信, B不是直接向A發起連接,而是通過服務器給A轉發一個連接請求,反過來請求A連接到B(即進行反向鏈接),A在收到從服務器轉發過來的請求以后,會主動向B發起一個TCP的連接請求,這樣在NAT設備上就會建立起關于這個連接的相關表項,使A和B之間能夠正常通信,從而建立起它們之間的TCP連接。

圖3 - 反向鏈接示意圖:
在這里插入圖片描述

3、基于UDP協議的P2P打洞技術詳解

3.1、原理概述

UDP打洞技術是通過中間服務器的協助在各自的NAT網關上建立相關的表項,使P2P連接的雙方發送的報文能夠直接穿透對方的NAT網關,從而實現P2P客戶端互連。如果兩臺位于NAT設備后面的P2P客戶端希望在自己的NAT網關上打個洞,那么他們需要一個協助者——集中服務器,并且還需要一種用于打洞的Session建立機制。

什么是集中服務器?
集中服務器本質上是一臺被設置在公網上的服務器,建立P2P的雙方都可以直接訪問到這臺服務器。位于NAT網關后面的客戶端A和B都可以與一臺已知的集中服務器建立連接,并通過這臺集中服務器了解對方的信息并中轉各自的信息。

同時集中服務器的另一個重要作用在于判斷某個客戶端是否在NAT網關之后。具體的方法是:一個客戶端在集中服務器上登陸的時候,服務器記錄下該客戶端的兩對地址二元組信息{IP地址:UDP端口},一對是該客戶端與集中服務器進行通信的自身的IP地址和端口號,另一對是集中服務器記錄下的由服務器“觀察”到的該客戶端實際與自己通信所使用的IP地址和端口號。我們可以把前一對地址二元組看作是客戶端的內網IP地址和端口號,把后一對地址二元組看作是客戶端的內網IP地址和端口號經過NAT轉換后的外網IP地址和端口號。集中服務器可以從客戶端的登陸消息中得到該客戶端的內網相關信息,還可以通過登陸消息的IP頭和UDP頭得到該客戶端的外網相關信息。如果該客戶端不是位于NAT設備后面,那么采用上述方法得到的兩對地址二元組信息是完全相同的。

P2P的Session建立原理:
假定客戶端A要發起對客戶端B的直接連接,具體的“打洞”過程如下:
1)A最初不知道如何向客戶端B發起連接,于是A向集中服務器發送消息,請求集中服務器幫助建立與客戶端B的UDP連接。
2)集中服務器將含有B的外網和內網的地址二元組發給A,同時,集中服務器將包含有A的外網和內網的地址二元組信息的消息也發給B。這樣一來, A與B就都知道對方外網和內網的地址二元組信息了。
3)當A收到由集中服務器發來的包含B的外網和內網的地址二元組信息后, A開始向B的地址二元組發送UDP數據包,并且A會自動鎖定第一個給出響應的B的地址二元組。同理,當B收到由集中服務器發來的A的外網和內網地址二元組信息后,也會開始向A的外網和內網的地址二元組發送UDP數據包,并且自動鎖定第一個得到A回應的地址二元組。由于A與B互相向對方發送UDP數據包的操作是異步的,所以A和B發送數據包的時間先后并沒有時序要求。

下面來看下這三者之間是如何進行UDP打洞的。在這我們分三種具體情景來討論:
第一種是最簡單的一種情景,兩個客戶端都位于同一個NAT設備后面,即位于同一內網中;
第二種是最普遍的一種情景,兩個客戶端分別位于不同的NAT設備后面,分屬不同的內網;
第三種是客戶端位于兩層NAT設備之后,通常最上層的NAT是由網絡提供商提供的,第二層NAT是家用的NAT路由器之類的設備提供的。

3.2、典型P2P情景1: 兩客戶端位于同一NAT設備后面(即相同內網中)

這是最簡單的一種情況(如圖4所示):客戶端A和B分別與集中服務器建立UDP連接,經過NAT轉換后,A的公網端口被映射為62000,B的公網端口映射為62005。

圖4 - 位于同一個NAT設備后的UDP打洞過程:
在這里插入圖片描述
當A向集中服務器發出消息請求與B進行連接,集中服務器將B的外網地址二元組以及內網地址二元組發給A,同時把A的外網以及內網的地址二元組信息發給B。A和B發往對方公網地址二元組信息的UDP數據包不一定會被對方收到,這取決于當前的NAT設備是否支持不同端口之間的UDP數據包能否到達(即Hairpin轉換特性),無論如何A與B發往對方內網的地址二元組信息的UDP數據包是一定可以到達的,內網數據包不需要路由,且速度更快。A與B推薦采用內網的地址二元組信息進行常規的P2P通信。

假定NAT設備支持Hairpin轉換,P2P雙方也應忽略與內網地址二元組的連接,如果A 和B采用外網的地址二元組做為P2P通信的連接,這勢必會造成數據包無謂地經過NAT設備,這是一種對資源的浪費。就目前的網絡情況而言,應用程序在“打洞”的時候,最好還是把外網和內網的地址二元組都嘗試一下。如果都能成功,優先以內網地址進行連接。

什么是Hairpin技術?
Hairpin技術又被稱為Hairpin NAT、Loopback NAT或Hairpin Translation。Hairpin技術需要NAT網關支持,它能夠讓兩臺位于同一臺NAT網關后面的主機,通過對方的公網地址和端口相互訪問,NAT網關會根據一系列規則,將對內部主機發往其NAT公網IP地址的報文進行轉換,并從私網接口發送給目標主機。目前有很多NAT設備不支持該技術,這種情況下,NAT網關在一些特定場合下將會阻斷P2P穿越NAT的行為,打洞的嘗試是無法成功的。好在現在已經有越來越多的NAT設備商開始加入到對該轉換的支持中來。

3.3、典型P2P情景2: 兩客戶端位于不同的NAT設備后面(分屬不同的內網)

這是最普遍的一種情況(如圖5所示):客戶端A與B經由各自的NAT設備與集中服務器建立UDP連接, A與B的本地端口號均為4321,集中服務器的公網端口號為1234。在向外的會話中, A的外網IP被映射為155.99.25.11,外網端口為62000;B的外網IP被映射為138.76.29.7,外網端口為31000。

如下所示:
客戶端A——>本地IP:10.0.0.1,本地端口:4321,外網IP:155.99.25.11,外網端口:62000
客戶端B——>本地IP:10.1.1.3,本地端口:4321,外網IP:138.76.29.7,外網端口:31000

圖5 - 位于不同NAT設備后的UDP打洞過程:
在這里插入圖片描述
在A向服務器發送的登陸消息中,包含有A的內網地址二元組信息,即10.0.0.1:4321;服務器會記錄下A的內網地址二元組信息,同時會把自己觀察到的A的外網地址二元組信息記錄下來。同理,服務器也會記錄下B的內網地址二元組信息和由服務器觀察到的客戶端B的外網地址二元組信息。無論A與B二者中的任何一方向服務器發送P2P連接請求,服務器都會將其記錄下來的上述的外網和內網地址二元組發送給A或B。

A和B分屬不同的內網,它們的內網地址在外網中是沒有路由的,所以發往各自內網地址的UDP數據包會發送到錯誤的主機或者根本不存在的主機上。當A的第一個消息發往B的外網地址(如圖3所示),該消息途經A的NAT設備,并在該設備上生成一個會話表項,該會話的源地址二元組信息是{10.0.0.1:4321},和A與服務器建立連接的時候NAT生成的源地址二元組信息一樣,但它的目的地址是B的外網地址。在A的NAT設備支持保留A的內網地址二元組信息的情況下,所有來自A的源地址二元組信息為{10.0.0.1:4321}的數據包都沿用A與集中服務器事先建立起來的會話,這些數據包的外網地址二元組信息均被映射為{155.99.25.11:62000}。

A向B的外網地址發送消息的過程就是“打洞”的過程,從A的內網的角度來看應為從{10.0.0.1:4321}發往{138.76.29.7:31000},從A在其NAT設備上建立的會話來看,是從{155.99.25.11:62000}發到{138.76.29.7:31000}。如果A發給B的外網地址二元組的消息包在B向A發送消息包之前到達B的NAT設備,B的NAT設備會認為A發過來的消息是未經授權的外網消息,并丟棄該數據包。

B發往A的消息包也會在B的NAT設備上建立一個{10.1.1.3:4321,155.99.25.11:62000}的會話(通常也會沿用B與集中服務器連接時建立的會話,只是該會話現在不僅接受由服務器發給B的消息,還可以接受從A的NAT設備{155.99.25.11:6200}發來的消息)。

一旦A與B都向對方的NAT設備在外網上的地址二元組發送了數據包,就打開了A與B之間的“洞”,A與B向對方的外網地址發送數據,等效為向對方的客戶端直接發送UDP數據包了。一旦應用程序確認已經可以通過往對方的外網地址發送數據包的方式讓數據包到達NAT后面的目的應用程序,程序會自動停止繼續發送用于“打洞”的數據包,轉而開始真正的P2P數據傳輸。

3.4、典型P2P情景3: 兩客戶端位于兩層(或多層)NAT設備之后(分屬不同的內網)

此種情景最典型的部署情況就像這樣:最上層的NAT設備通常是由網絡提供商(ISP)提供,下層NAT設備是家用路由器。

如圖6所示:假定NAT C是由ISP提供的NAT設備,NAT C提供將多個用戶節點映射到有限的幾個公網IP的服務,NAT A和NAT B作為NAT C的內網節點將把用戶的內部網絡接入NAT C的內網,用戶的內部網絡就可以經由NAT C訪問公網了。從這種拓撲結構上來看,只有服務器與NAT C是真正擁有公網可路由IP地址的設備,而NAT A和NAT B所使用的公網IP地址,實際上是由ISP服務提供商設定的(相對于NAT C而言)內網地址(我們將這種由ISP提供的內網地址稱之為“偽”公網地址)。同理,隸屬于NAT A與NAT B的客戶端,它們處于NAT A,NAT B的內網,以此類推,客戶端可以放到到多層NAT設備后面。客戶端A和客戶端B發起對服務器S的連接的時候,就會依次在NAT A和NAT B上建立向外的Session,而NAT A、NAT B要聯入公網的時候,會在NAT C上再建立向外的Session。

圖6 - 多層NAT下的打洞過程:
在這里插入圖片描述
現在假定客戶端A和B希望通過UDP“打洞”完成兩個客戶端的P2P直連。最優化的路由策略是客戶端A向客戶端B的“偽公網”IP上發送數據包,即ISP服務提供商指定的內網IP,NAT B的“偽”公網地址二元組,{10.0.1.2:55000}。由于從服務器的角度只能觀察到真正的公網地址,也就是NAT A,NAT B在NAT C建立session的真正的公網地址{155.99.25.11:62000}以及{155.99.25.11:62005},非常不幸的是客戶端A與客戶端B是無法通過服務器知道這些“偽”公網的地址,而且即使客戶端A和B通過某種手段可以得到NAT A和NAT B的“偽”公網地址,我們仍然不建議采用上述的“最優化”的打洞方式,這是因為這些地址是由ISP服務提供商提供的或許會存在與客戶端本身所在的內網地址重復的可能性(例如:NAT A的內網的IP地址域恰好與NAT A在NAT C的“偽”公網IP地址域重復,這樣就會導致打洞數據包無法發出的問題)。

因此客戶端別無選擇,只能使用由公網服務器觀察到的A,B的公網地址二元組進行“打洞”操作,用于“打洞”的數據包將由NAT C進行轉發。

當客戶端A向客戶端B的公網地址二元組{155.99.25.11:62005}發送UDP數據包的時候,NAT A首先把數據包的源地址二元組由A的內網地址二元組{10.0.0.1:4321}轉換為“偽”公網地址二元組{10.0.1.1:45000},現在數據包到了NAT C,NAT C應該可以識別出來該數據包是要發往自身轉換過的公網地址二元組,如果NAT C可以給出“合理”響應的話,NAT C將把該數據包的源地址二元組改為{155.99.25.11:62000},目的地址二元組改為{10.0.1.2:55000},即NAT B的“偽”公網地址二元組,NAT B最后會將收到的數據包發往客戶端B。同樣,由B發往A的數據包也會經過類似的過程。目前也有很多NAT設備不支持類似這樣的“Hairpin轉換”,但是已經有越來越多的NAT設備商開始加入對該轉換的支持中來。

3.5、一個需要考慮的現實問題:UDP在空閑狀態下的超時

當然,從應用的角度上來說,在完成打洞過程的同時,還有一些技術問題需要解決,如UDP在空閑狀態下的超時問題。由于UDP轉換協議提供的“洞”不是絕對可靠的,多數NAT設備內部都有一個UDP轉換的空閑狀態計時器,如果在一段時間內沒有UDP數據通信,NAT設備會關掉由“打洞”過程打出來的“洞”。如果P2P應用程序希望“洞”的存活時間不受NAT網關的限制,就最好在穿越NAT以后設定一個穿越的有效期。

對于有效期目前沒有標準值,它與NAT設備內部的配置有關,某些設備上最短的只有20秒左右。在這個有效期內,即使沒有P2P數據包需要傳輸,應用程序為了維持該“洞”可以正常工作,也必須向對方發送“打洞”心跳包。這個心跳包是需要雙方應用程序都發送的,只有一方發送不會維持另一方的Session正常工作。除了頻繁發送“打洞”心跳包以外,還有一個方法就是在當前的“洞”超時之前,P2P客戶端雙方重新“打洞”,丟棄原有的“洞”,這也不失為一個有效的方法。

4、基于TCP協議的P2P打洞技術詳細

建立穿越NAT設備的P2P的TCP連接只比UDP復雜一點點,TCP協議的”“打洞”從協議層來看是與UDP的“打洞”過程非常相似的。盡管如此,基于TCP協議的打洞至今為止還沒有被很好的理解,這也造成了的對其提供支持的NAT設備不是很多。在NAT設備支持的前提下,基于TCP的“打洞”技術實際上與基于UDP的“打洞”技術一樣快捷、可靠。實際上,只要NAT設備支持的話,基于TCP的P2P技術的健壯性將比基于UDP技術的更強一些,因為TCP協議的狀態機給出了一種標準的方法來精確的獲取某個TCP session的生命期,而UDP協議則無法做到這一點。

4.1、套接字和TCP端口的重用

實現基于TCP協議的P2P打洞過程中,最主要的問題不是來自于TCP協議,而是來自于應用程序的API接口。這是由于標準的伯克利(Berkeley)套接字的API是圍繞著構建客戶端/服務器程序而設計的,API允許TCP流套接字通過調用connect()函數來建立向外的連接,或者通過listen()和accept函數接受來自外部的連接,但是,API不提供類似UDP那樣的,同一個端口既可以向外連接,又能夠接受來自外部的連接。而且更糟的是,TCP的套接字通常僅允許建立1對1的響應,即應用程序在將一個套接字綁定到本地的一個端口以后,任何試圖將第二個套接字綁定到該端口的操作都會失敗。

為了讓TCP“打洞”能夠順利工作,我們需要使用一個本地的TCP端口來監聽來自外部的TCP連接,同時建立多個向外的TCP連接。幸運的是,所有的主流操作系統都能夠支持特殊的TCP套接字參數,通常叫做“SO_REUSEADDR”,該參數允許應用程序將多個套接字綁定到本地的一個地址二元組(只要所有要綁定的套接字都設置了SO_REUSEADDR參數即可)。BSD系統引入了SO_REUSEPORT參數,該參數用于區分端口重用還是地址重用,在這樣的系統里面,上述所有的參數必須都設置才行。

4.2、打開P2P的TCP流

假定客戶端A希望建立與B的TCP連接。我們像通常一樣假定A和B已經與公網上的已知服務器建立了TCP連接。服務器記錄下來每個接入的客戶端的公網和內網的地址二元組,如同為UDP服務的時候一樣。

從協議層來看,TCP“打洞”與UDP“打洞”是幾乎完全相同的過程:
1、 客戶端A使用其與服務器的連接向服務器發送請求,要求服務器協助其連接客戶端B;

2、 服務器將B的公網和內網的TCP地址的二元組信息返回給A,同時,服務器將A的公網和內網的地址二元組也發送給B;

3、客戶端A和B使用連接服務器的端口異步地發起向對方的公網、內網地址二元組的TCP連接,同時監聽各自的本地TCP端口是否有外部的連接聯入;

4、A和B開始等待向外的連接是否成功,檢查是否有新連接聯入。如果向外的連接由于某種網絡錯誤而失敗,如:“連接被重置”或者“節點無法訪問”,客戶端只需要延遲一小段時間(例如延遲一秒鐘),然后重新發起連接即可,延遲的時間和重復連接的次數可以由應用程序編寫者來確定;

5、TCP連接建立起來以后,客戶端之間應該開始鑒權操作,確保目前聯入的連接就是所希望的連接。如果鑒權失敗,客戶端將關閉連接,并且繼續等待新的連接聯入。客戶端通常采用“先入為主”的策略,只接受第一個通過鑒權操作的客戶端,然后將進入P2P通信過程不再繼續等待是否有新的連接聯入。

圖7 - TCP打洞:
在這里插入圖片描述
與UDP不同的是,因為使用UDP協議的每個客戶端只需要一個套接字即可完成與服務器的通信,而TCP客戶端必須處理多個套接字綁定到同一個本地TCP端口的問題,如圖7所示。現在來看實際中常見的一種情景,A與B分別位于不同的NAT設備后面,如圖5所示,并且假定圖中的端口號是TCP協議的端口號,而不是UDP的端口號。圖中向外的連接代表A和B向對方的內網地址二元組發起的連接,這些連接或許會失敗或者無法連接到對方。如同使用UDP協議進行“打洞”操作遇到的問題一樣,TCP的“打洞”操作也會遇到內網的IP與“偽”公網IP重復造成連接失敗或者錯誤連接之類的問題。

客戶端向彼此公網地址二元組發起連接的操作,會使得各自的NAT設備打開新的“洞”允許A與B的TCP數據通過。如果NAT設備支持TCP“打洞”操作的話,一個在客戶端之間的基于TCP協議的流通道就會自動建立起來。如果A向B發送的第一個SYN包發到了B的NAT設備,而B在此前沒有向A發送SYN包,B的NAT設備會丟棄這個包,這會引起A的“連接失敗”或“無法連接”問題。而此時,由于A已經向B發送過SYN包,B發往A的SYN包將被看作是由A發往B的包的回應的一部分,所以B發往A的SYN包會順利地通過A的NAT設備,到達A,從而建立起A與B的P2P連接。

4.3、從應用程序的角度來看TCP“打洞”

從應用程序的角度來看,在進行TCP“打洞”的時候都發生了什么呢?假定A首先向B發出SYN包,該包發往B的公網地址二元組,并且被B的NAT設備丟棄,但是B發往A的公網地址二元組的SYN包則通過A的NAT到達了A,然后,會發生以下的兩種結果中的一種,具體是哪一種取決于操作系統對TCP協議的實現:

(1)
A的TCP實現會發現收到的SYN包就是其發起連接并希望聯入的B的SYN包,通俗一點來說就是“說曹操,曹操到”的意思,本來A要去找B,結果B自己找上門來了。A的TCP協議棧因此會把B作為A向B發起連接connect的一部分,并認為連接已經成功。程序A調用的異步connect()函數將成功返回,A的listen()等待從外部聯入的函數將沒有任何反映。此時,B聯入A的操作在A程序的內部被理解為A聯入B連接成功,并且A開始使用這個連接與B開始P2P通信。

由于收到的SYN包中不包含A需要的ACK數據,因此,A的TCP將用SYN-ACK包回應B的公網地址二元組,并且將使用先前A發向B的SYN包一樣的序列號。一旦B的TCP收到由A發來的SYN-ACK包,則把自己的ACK包發給A,然后兩端建立起TCP連接。簡單的說,第一種,就是即使A發往B的SYN包被B的NAT丟棄了,但是由于B發往A的包到達了A。結果是,A認為自己連接成功了,B也認為自己連接成功了,不管是誰成功了,總之連接是已經建立起來了。

(2)
另外一種結果是,A的TCP實現沒有像(1)中所講的那么“智能”,它沒有發現現在聯入的B就是自己希望聯入的。就好比在機場接人,明明遇到了自己想要接的人卻不認識,誤認為是其他的人,安排別人給接走了,后來才知道是自己錯過了機會,但是無論如何,人已經接到了任務已經完成了。然后,A通過常規的listen()函數和accept()函數得到與B的連接,而由A發起的向B的公網地址二元組的連接會以失敗告終。盡管A向B的連接失敗,A仍然得到了B發起的向A的連接,等效于A與B之間已經聯通,不管中間過程如何,A與B已經連接起來了,結果是A和B的基于TCP協議的P2P連接已經建立起來了。

第一種結果適用于基于BSD的操作系統對于TCP的實現,而第二種結果更加普遍一些,多數Linux和Windows系統都會按照第二種結果來處理。

5、本文小結

在IP地址極度短缺的今天,NAT幾乎已經是無所不在的一項技術了,以至于現在任何一項新技術都不得不考慮和NAT的兼容。作為當下應用最廣泛的技術之一,P2P技術也必然要面對NAT這個障礙。

打洞技術看起來是一項近似乎蠻干的技術,卻不失為一種有效的技術手段。在集中服務器的幫助下,P2P的雙方利用端口預測的技術在NAT網關上打出通道,從而實現NAT穿越,解決了NAT對于P2P的阻隔,為P2P技術在網絡中更廣泛的推廣作出了非常大的貢獻。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/378852.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/378852.shtml
英文地址,請注明出處:http://en.pswp.cn/news/378852.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java Byte類的compareTo()方法和示例

簡短的類compareTo()方法 (Short class compareTo() method) compareTo() method is available in java.lang package. compareTo()方法在java.lang包中可用。 compareTo() method is used to check equality or inequality for this Byte object against the given Byte objec…

顯示照片的RGB直方圖

顯示照片的RGB直方圖 import numpy as np import cv2 as cv from matplotlib import pyplot as plt img cv.imread(E:\Python-workspace\OpenCV\OpenCV/BEYOND.png,1)#第一個參數為選擇照片的路徑,注意照片路徑最后一個為正斜杠其他都為反斜杠;第二個參…

OUT還開通博客!

現在哪有人還在玩博客哦,哎試試,記錄一下自己開發網站的點滴吧!轉載于:https://www.cnblogs.com/17say/archive/2013/02/18/2915125.html

網站V5的一些想法(轉)

V5即將到來,面對“全新”的V5,前端這塊自然也要借這次改版的機會,將我們前端的一些想法實踐到V5中去,實現一次跨越。 1 嘗試模塊化的代碼書寫(html、css等) 模塊化的目的是為了提高代碼的重用性、擴展性、可維護性 2 文件引用使用…

mysql慢查詢開啟語句分析_mysql慢查詢語句分析總結

我們經常會接觸到MySQL,也經常會遇到一些MySQL的性能問題。我們可以借助慢查詢日志和explain命令初步分析出SQL語句存在的性能問題通過SHOW FULL PROCESSLIST查看問題SHOW FULL PROCESSLIST相當于select * from information_schema.processlist可以列出正在運行的連…

P2P技術詳解(三):P2P中的NAT穿越(打洞)方案詳解(進階分析篇)

目錄1、NAT和NAPT2、NAT帶來的問題3、P2P通信穿越NAT的技術、方法4、NAT穿越技術1:應用層網關4.1、原理4.2、限制5、NAT穿越技術2:中間件技術5.1、原理5.2、限制6、NAT穿越技術3:打洞技術(Hole Punching)6.1、原理6.2、方法6.2.1NAT行為類型與…

Java BufferedReader reset()方法及示例

BufferedReader類的reset()方法 (BufferedReader Class reset() method) reset() method is available in java.io package. reset()方法在java.io包中可用。 reset() method is used to reset the stream to the most recent mark of this stream. reset()方法用于將流重置為該…

將兩大小完全相同的照片進行加權混合對比

將兩張大小完全相同的照片進行加權混合對比 import cv2 img1cv2.imread(E:\Python-workspace\OpenCV\OpenCV/water1.png,1)#第一個參數為選擇照片的路徑,注意照片路徑最后一個為正斜杠其他都為反斜杠;第二個參數,其中1表示所選照片為彩色照片…

過了很久了

很久沒來這里了,一般也就找找資料會上一下子。差不多算是荒廢了吧 不要緊,開始寫了轉載于:https://www.cnblogs.com/Anykong/archive/2013/02/18/2916333.html

古文中驚艷的句子

-1】終于為那一身江南煙雨覆了天下,容華謝后,不過一場,山河永寂。-2】千秋功名,一世葬你,玲瓏社稷,可笑卻無君王命。-3】鳳凰臺上鳳凰游,負約而去,一夜苦等,從此江南江北…

java 方法 示例_Java ArrayDeque pollFirst()方法與示例

java 方法 示例ArrayDeque類pollFirst()方法 (ArrayDeque Class pollFirst() method) pollFirst() Method is available in java.lang package. pollFirst()方法在java.lang包中可用。 pollFirst() Method is used to return the first element of the queue denoted by this d…

P2P技術詳解(四):P2P技術之STUN、TURN、ICE詳解

目錄1、內容概述2、STUN詳解2.1 RFC3489/STUN2.1.1 報文結構2.1.2實現原理2.1.3STUN功能舉例2.2 RFC5389/STUN2.2.1STUN用途2.2.2報文結構2.3 RFC5389與RFC3489的區別2.4 新特性介紹2.4.1指紋機制2.4.2通過DNS發現服務器機制2.4.3認證和消息完整性機制2.4.4備份服務器機制2.5 R…

比較兩張大小相同的照片的差異,返回數值

比較兩張大小相同的照片的差異,返回數值 from PIL import Image import math import operator from functools import reducedef image_contrast(img1, img2):image1 Image.open(img1)image2 Image.open(img2)h1 image1.histogram()h2 image2.histogram()resul…

poj2115C Looooops

http://poj.org/problem?id2115 參考人家的 如下 如i65534,當i3時,i1 其實就是 i(655343)%(2^16)1 有了這些思想,設對于某組數據要循環x次結束,那么本題就很容易得到方程: x[(B-A2^k)%2^k] /C 即 Cx(B-A)(mod 2^k) 此…

ASP.NET調用javascript腳本的常見方法小結

http://www.codesky.net/article/doc/201004/2010041706872.htm轉載于:https://www.cnblogs.com/ZC_Mo-Blog/archive/2010/11/23/1885125.html

python wait方法_Python條件類| 帶有示例的wait()方法

python wait方法Python Condition.wait()方法 (Python Condition.wait() Method) wait() is an inbuilt method of the Condition class of the threading module in Python. wait()是Python中線程模塊的Condition類的內置方法。 Condition class implements condition variab…

return編程python_python3 第二十一章 - 函數式編程之return函數和閉包

我們來實現一個可變參數的求和。通常情況下,求和的函數是這樣定義的:def calc_sum(*args):ax0for n inargs:ax ax nreturn ax但是,如果不需要立刻求和,而是在后面的代碼中,根據需要再計算怎么辦?可以不返回…

黑色背景下,計算照片白色的區域面積和周長

黑色背景下,計算照片白色的區域面積和周長 import cv2 img cv2.imread(E:\Python-workspace\OpenCV\OpenCV/beyond.png,1)#第一個參數為選擇照片的路徑,注意照片路徑最后一個為正斜杠其他都為反斜杠;第二個參數,其中1表示所選照…

php連接mssql數據庫的幾種方式

數據庫查詢不外乎4個步驟,1、建立連接。2、輸入查詢代碼。3、建立查詢并取出數據。4、關閉連接。 php連接mssql數據庫有幾個注意事項,尤其mssql的多個版本、32位、64位都有區別。 首先,php.ini文件中;extensionphp_pdo_mssql.dll ;extensionp…

通俗易懂:快速理解P2P技術中的NAT穿透原理

目錄1、基礎知識1.1、什么是NAT?1.2、為什么會有NAT?1.3、NAT有什么優缺點?2、NAT的實現方式2.1、靜態NAT2.2、NAPT3、NAT的主要類型3.1、完全錐型NAT(Full Cone NAT,后面簡稱FC)3.2、受限錐型NAT&#xff…