1. 程式人生 > >關於使用UDP(TCP)跨區域網,NAT穿透的心得

關於使用UDP(TCP)跨區域網,NAT穿透的心得

前言:
       最近我用java做了一個C/S的類似QQ之類的IM系統(即時通訊系統),遇到了不能跨區域網通訊問題,經過在網上,和書上查閱了一些資料,瞭解了一些情況,現在就總結一下我的解決方案吧(本人也是在不斷錯誤中學習,如果有什麼不對的地方,請大家多多指教)。


問題描述:
         一般情況下,只能在同一個子網即同一個虛擬局網裡通訊,或者子網訪問外網,外網訪問不了內網。因為虛擬局域網相對於外網都是透明的,所以外網是不能直接訪問子網,舉個例子:校園網裡的學生資訊管理系統(MIS),需要是校園網裡面的IP地址才能訪問,校園網以外的IP是不能訪問,這樣的做法的好處不用我多說

吧。。
而即時通訊需要相互交流資訊,所以需要相互都能訪問到,問題是:如何跨子網通訊?

問題分析:

首先,在不同網路點之間(即peer-to-peer對等網路),可以分為以下幾種情況:


1.ClientA在子網,ClientB也在同一個子網
2.ClientA在子網,ClientB在外網

3.ClientA在一個子網內,ClientB在另一個子網內


對於第一種情況,不需要經過路由器的轉發,可以直接相互通訊。


對於第二種情況,ClientB對於ClientA是公開的,ClientA對於ClientB是透明的。

ClientA-->直接相通-->ClientB,ClientB-->不能直接想通-->ClientA。換句話說,ClientA都能接受到包涵真正傳送者IP的資料包;如果ClientA傳送資料包給ClientB,ClientB接受資料包的IP來源並不是ClientA,而已中轉站(路由器)的IP。


對於第三種情況,兩者之間都是相互透明的。



解決方案:

要解決P2P跨區域網,就要用到NAT穿透技術,我在這裡先講UDP穿透,TCP穿透原理一樣,實現更簡單,這裡就不多說了。

NAT的全稱是Network Address Translator,網路地址轉換。一般是應用於路由器,更詳細資料請自己查閱資料

吧。
NAT分兩大類:
1)NAT
2)NAPT ,Network Address Port Translator,網路地址埠轉換
這裡預設是用NAT,埠號沒有轉換,如果是NAPT,實現的原理也是差不多的,只是細節不同。


關於第二種情況,原理如下
A:192.168.1.10,處於內網
NATA:路由器對外的wlanIP:168.38.2.2;路由器對內的lanIP:192.168.1.10
B:168.38.2.225,處於外網


1.首先,A(內網IP)先向B(外網IP)傳送UDP包,NAT會產生session,存放192.168.1.10-- >168.38.2.225的對映關係


此時,A為了B在NAT上打了一個洞




2.接下來,只要B把資訊發給NATA,NATA會自動把資訊轉發給A



這樣A,B之間的NATA會有個洞來讓兩者通訊,但是此方案不適用於第三種情況。



關於第三種情況,原理如下

需要用到第三方中轉站,而且這中轉站必須在外網,即全球唯一IP。我是直接一臺連線所有客戶端的服器,記錄了所有客戶端的真實IP(如果是內網IP就記錄內網IP),我是用TCP來實現客戶端和伺服器的通訊,裡要用到了TCP穿透,這裡先不講,最後總結說一下。



或者如圖:(ps:圖片是網上下載的)

首先,我先介紹下這個伺服器的作用。所有的客戶端都和伺服器建立了面向連線可靠的TCP連線,即服器--客戶端之間可以相互通訊。客戶端會向客戶端傳送自身的真實IP(如A:192.168.1.110),伺服器接受到資訊之後,同時也會知道資訊源的IP(如:NATA的外網IP:210.38.196.110),因為接受方總能知道資訊包的直接來源。此時,伺服器就記錄了ClientA的IP、NATA外網IP和ClientB的IP、NATB外網IP。


要想A<------>B之間無需經過第三方的通訊,必須在NATA中為B打個洞,在NATB中為A打個洞。

實際上就是在NATA中存放A(192.168.1.110)--->NATB(外網IP:210.38.196.30)的對映,這樣只要是從NATB傳送到NATA的,都會轉發到A子網中,此過程叫NATA為B打洞。同理NATB也可以為A打洞。


具體過程:server會發送資訊告知A,B的NATB的外網IP;告知B,A的NATA的外網IP。這樣子,A可以先傳送一個數據包到NATB(外網IP:210.38.196.30),NATA會生成一個session記錄A————>NATB的對映關系。數據包到達NATB時,NATB因為還未為A打洞,會丟包。然後B向NATA(外網IP:210.38.196.110)傳送數據包,NATB會生成一個session記錄B————>NATA的對映關係。此時,NATA接受到來自NATB的資料包,會查詢下session對映,發現有A————>NATB的對映關係,會把包轉發給A。只要A再發資訊給NATB時,NATB也會根據session來轉發給B。雙方打洞完成。

所以對於第二種情況,也可以用此方案,如圖:

利用第三方伺服器來幫P2P對等點之間的UDP打洞,是比較全面的方案,此方案適用於P2P對等點在任何網絡點(說得可能比較絕對吧,大家有什麼不同意見記得提出來哦,純屬個人的偏見)



總結:

簡單說下TCP穿透原理吧,分四種情況:

1.建立TCP等待連線方和請求TCP連線方在同一個子網,或者是外網(不用穿透)

2.建立TCP等待連線方在外網,請求TCP連線方在內網(請求方會先發請求資訊,同時為建立方打洞)
3.建立TCP等待連線方在內網,請求TCP連線方在外網(需要第三方伺服器,原理同上面的UDP穿透一樣)
4.建立TCP等待連線方,請求TCP連線方分別在不同的子網(需要第三方伺服器,原理同上面的UDP穿透一樣)


不足:由於我開發的只是簡單的即時通訊系統,可能很多複雜的情況我沒有考慮進去,例如存在多個NAT的嵌套,NAPTIP地址埠號轉換沒有考慮進去,路由器中的session的生命週期的不確定(有時候是幾分鍾,有時候幾個小時不定),所以需要定期地進行穿透等等等等。