你沒有發佈stunclient
運行的結果,但我想它看起來像下面這樣:
$ stunclient --mode full --localport 9999 stun.stunprotocol.org
Binding test: success
Local address: 192.168.1.8:9999
Mapped address: 1.2.3.4:9999
Behavior test: success
Nat behavior: Endpoint Independent Mapping
Filtering test: success
Nat filtering: Address and Port Dependent Filtering
我要去猜測,你的行爲測試是「獨立於終端」,過濾測試是「地址和端口相關」,因爲這些在家庭中最常見,並且大部分與您上面描述的相匹配。 (又稱「限制端口的NAT」)。
無論如何,這意味着你已經在你自己和STUN服務器之間創建了一個端口映射。在上面的例子中,我的公共IP地址是1.2.3.4。這是常見的,但並非總是如此,我的本地端口(9999)與公共端口相同。
內部,NAT還記錄着一個邏輯表如下所示:
------------------------------------------------------------------------------------
|| LOCAL IP | LOCAL PORT || EXT PORT || REMOTE IP | REMOTE PORT ||
||================================================================================||
|| 192.168.1.8 | 9999 || 9999 || 107.23.150.92 | 3478 ||
------------------------------------------------------------------------------------
因爲你從端口9999發送出去的數據包到STUN服務器(107.23.150.92),該NAT創建一個端口映射條目在桌上幾分鐘。當數據包從互聯網到達NAT /路由器時,它會查詢表格。當響應從STUN服務器的IP:端口返回時,NAT能夠基於上表中的「遠程」字段將其轉發到NAT後面的計算機。
但是,您和希望從中接收數據的「其他公共機器」之間沒有端口映射。我們假設另一臺機器的IP地址是2.4.6.8,並且它試圖從它的本地端口8888發送。表中的NAT仍然沒有任何東西來將流量從2.4.6.8:8888映射到後面的主機NAT。因此,當流量從不在表中的主機到達NAT時,NAT只知道將數據包丟棄在地面上。有一種稱爲「Cone NAT」的NAT分類,這可以起作用,但這些分類並不常見。
在你的情況下,有一個簡單的解決方法。從STUN服務器獲取端口映射後,從同一本地端口(9999)發送另一個數據報到您想從其接收數據的遠程主機(和遠程端口)。遠程主機可以簡單地忽略這個數據包,但它有效地創建你的NAT
------------------------------------------------------------------------------------
|| LOCAL IP | LOCAL PORT || EXT PORT || REMOTE IP | REMOTE PORT ||
||================================================================================||
|| 192.168.1.8 | 9999 || 9999 || 107.23.150.92 | 3478 ||
|| 192.168.1.8 | 9999 || 9999 || 2.4.6.8 | 8888 ||
------------------------------------------------------------------------------------
這個簡單的1字節的數據包到2.4.6另一個端口映射條目。8:8888允許NAT將流量從該地址轉發回NAT後面的主機。
換句話說,利用自己的網絡流量的命名:
My machine:9999 ---->[STUN BINDING REQUEST]--->stun server:3478
My machine:9999 <----[STUN BINDING RESPONSE mapped IP:port]<--- stun server:3478
My machine:9999 [Open socket on port 9999]
My machine:9999 ---->[1 byte datagram] -------> 'other:8888'
My machine:9999 <---- [UDP to public IP:port obtained in step 2]<----'other:8888'
通常,在一個正常的P2P流量,兩個端點與STUN服務器工作,發現他們的端口映射。然後使用另一個服務來互相交換IP:端口信息。從你所描述的,你手動交換你的程序之間的這些值,這是很好的測試。
如果另一臺機器在公共互聯網上,您在技術上不需要STUN。第一臺機器(在NAT後面)可以直接發送到遠程IP和端口來說「給我發送一些數據」。遠程端只是檢查此消息的對端地址和端口,以決定發回的位置。端口映射已經被創建。一些RTSP客戶端假設服務器是公開的
我對套接字NAT穿越的基礎知識的回答是here。
我碰巧知道STUNTMAN的開發者。他是一個相當不錯的人,很帥,很聰明。他們也說他和我看起來很像,並且與我們的姓名拼寫很接近。如果您有關於STUN和NAT遍歷的問題,可以隨時直接給他發郵件。