国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 課堂 > 網絡協議 > 正文

TCP協議的NAT穿透技術使用方法

2020-04-29 13:42:46
字體:
來源:轉載
供稿:網友

    其實很早我就已經實現了使用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的一樣?,F在假設客戶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 的點對點連接就成功了。
(責任編輯:VEVB)

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 酉阳| 察雅县| 友谊县| 祁东县| 黄石市| 长沙市| 工布江达县| 辽阳市| 伊宁市| 绥中县| 民丰县| 娄烦县| 巴林右旗| 梓潼县| 陆川县| 从化市| 观塘区| 松滋市| 丰原市| 利津县| 布拖县| 龙海市| 永德县| 乌兰浩特市| 安徽省| 澄迈县| 上高县| 长子县| 宿迁市| 中牟县| 茶陵县| 临泉县| 伊吾县| 沧源| 苍山县| 南郑县| 靖边县| 宁河县| 临邑县| 城口县| 会理县|