其實很早我就已經實現了使用tcp協議穿透nat了,但是苦於一直沒有時間,所以沒有寫出來,現在終於放假有一點空閒,於是寫出來共享之。
一直以來,說起nat穿透,很多人都會被告知使用udp打孔這個技術,基本上沒有人會告訴你如何使用tcp協議去穿透(甚至有的人會直接告訴你tcp協議是無法實現穿透的)。但是,眾所周知的是,udp是乙個無連線的資料報協議,使用它就必須自己維護收發資料報的完整性,這常常會大大增加程式的複雜度,而且一些程式由於某些原因,必須使用tcp協議,這樣就常常令一些開發tcp網路程式的人員「談穿透色變」。那麼,使用tcp協議是不是就不能實現穿透呢?答案當然是否定的:tcp協議不僅能實現nat穿透,而且實現起來比udp穿透甚至還簡單一些。
要了解如何使用tcp穿透nat,就要首先看看如何使用udp穿透nat。
我們假設在兩個不同的區域網後面分別有2臺客戶機a和 b,ab所在的區域網都分別通過乙個路由器接入網際網路。網際網路上有一台伺服器s。
現在ab是無法直接和對方傳送資訊的,ab都不知道對方在網際網路上真正的ip和埠, ab所在的區域網的路由器只允許內部向外主動傳送的資訊通過。對於b直接傳送給a的路由器的訊息,路由會認為其「不被信任」而直接丟棄。
要實現 ab直接的通訊,就必須進行以下3步:a首先連線網際網路上的伺服器s並傳送一條訊息(對於udp這種無連線的協議其實直接初始會話傳送訊息即可),這樣s就獲取了a在網際網路上的實際終端(傳送訊息的ip和埠號)。接著 b也進行同樣的步驟,s就知道了ab在網際網路上的終端(這就是「打洞」)。接著s分別告訴a和b對方客戶端在網際網路上的實際終端,也即s告訴a客戶b的會話終端,s告訴b客戶a的會話終端。這樣,在ab都知道了對方的實際終端之後,就可以直接通過實際終端傳送訊息了(因為先前雙方都向外傳送過訊息,路由上已經有允許資料進出的訊息通道)。
用udp來實現以上3步不存在什麼理論上的問題,因為udp是無連線的協議,它允許socket進行「多對一」的通訊(即幾個具有不同ip和埠號的socket向乙個接收socket傳送訊息)。但是使用tcp就出現了問題:在一般情況下,tcp socket不允許在已經建立連線的埠上再進行監聽和使用該本地埠。換句話說,當ab連線上伺服器s後,s將ab的實際終端告訴對方,下一步本該是ab利用對方的實際終端進行直連,但這時你會發現對方的實際終端已經被占用了(就是各自連線到伺服器s的會話占用了終端),無法同時listen和 connect。於是很多人得出結論:tcp無法實現nat穿透。
於是問題的關鍵變成了如何復用乙個tcp連線的本地終端,這其實不是協議的問題,而是乙個api的問題。幸運的是,所有主流作業系統都支援乙個特定的tcp套接字選項——so_reuseaddr。這個選項允許將多個socket繫結到同乙個本地終端。我們建立socket的時候只要加上這麼一行:
setsockopt(socket, sol_socket, so_reuseaddr, &flag, len) ; //c++就這麼做
_client.setsocketoption(socketoptionlevel.socket, socketoptionname.reuseaddress, true) '這是vb.net 更加簡單
知道上面的知識就很好辦了,下面我來說說tcp協議的穿透流程:
機器布局還是和上面使用udp的一樣。現在假設客戶a想和客戶b建立tcp連線。
首先還是 ab分別和伺服器s分別建立連線,s記錄ab的網際網路實際終端。然後s分別向ab傳送對方的實際終端。接著,從a和b向s連線時使用的埠,ab都非同步呼叫connect函式連線對方的實際終端(就是s告訴的終端),同時,ab雙方都在同乙個本地埠監聽到來的連線(也可以先監聽,再connect更好)。由於雙方都向對方傳送了connect請求(假設各自的syn封包已經穿過了自己的nat),因此在對方connect請求到達本地的監聽埠時,路由器會認為這個請求是剛剛那個connect會話的一部分,是已經被許可的,本地監聽埠就會用syn-ack響應,同意連線。這樣,tcp穿透nat的點對點連線就成功了。
**中有乙個我自己封裝的模仿vb6 winsock的控制項zxmsocket,這個socket可以讓你設定是否使用so_reuseaddr引數,socket是事件驅動的。
如果你要測試**,需要使用乙個bat來啟動傳送和接收程式(檔案格式請參照bin/debug資料夾下的run.bat檔案),這個bat的功能是以命令列的方式告訴程式登入伺服器縮使用的使用者名稱,對於伺服器來說,這個使用者名稱必須是唯一的,當然,這可能有點不科學,但是這畢竟只是乙個demo。
nat 穿透原理
其實很早我就已經實現了使用tcp協議穿透nat了,但是苦於一直沒有時間,所以沒有寫出來,現在終於放假有一點空閒,於是寫出來共享之。一直以來,說起nat穿透,很多人都會被告知使用udp打孔這個技術,基本上沒有人會告訴你如何使用tcp協議去穿透 甚至有的人會直接告訴你tcp協議是無法實現穿透的 但是,眾...
NAT穿透技術原理及應用
相信很多人都聽說過nat技術。我們國家的公網ip太少了不夠用,促使了nat技術的興起。但是nat穿透技術又是什麼呢?nat123是如何實現穿透的?相似應用有花生殼,nat123,金萬維,等。以下分析了nat穿透技術的原理及應用及各種相關介紹。nat技術的定義 nat是一種網路位址翻譯技術,將內部私有...
NAT與NAT穿透 三
一直以來,說起nat穿透,很多人都會被告知使用udp打孔這個技術,基本上沒有人會告訴你如何使用tcp協議去穿透 甚至有的人會直接告訴你tcp協議是無法實現穿透的 但是,眾所周知的是,udp是乙個無連線的資料報協議,使用它就必須自己維護收發資料報的完整性,這常常會大大增加程式的複雜度,而且一些程式由於...