關於TCP打洞和UDP打洞

爲什麼網上講到的P2P打洞基本上都是基於UDP協議的打洞?難道TCP不可能打洞?還是TCP打洞難於實現?假設現在有內網客戶端A和內網客戶端B,有公網服務端S。如果A和B想要進行UDP通信,則必須穿透雙方的NAT路由。假設爲NAT-A和NAT-B。

A 發送數據包到公網S,B發送數據包到公網S,則S分別得到了A和B的公網IP,S也和A B 分別建立了會話,由S發到NAT-A的數據包會被NAT-A直接轉發給A,由S發到NAT-B的數據包會被NAT-B直接轉發給B,除了S發出的數據包之 外的則會被丟棄。所以:現在A B 都能分別和S進行全雙工通訊了,但是A B之間還不能直接通訊。

 

解決辦法是:A向B的公網IP發送一個數據包,則NAT-A能接收來自NAT-B的數據包並轉發給A了(即B現在能訪問A了);再由S命令B向A的公網IP發送一個數據包,則NAT-B能接收來自NAT-A的數據包並轉發給B了(即A現在能訪問B了)。以上就是“打洞”的原理。但是TCP和UDP在打洞上卻有點不同。這是因爲伯克利socket(標準socket規範)的API造成的。UDP的socket允許多個socket綁定到同一個本地端口,而TCP的socket則不允許。

 

這 是這樣一個意思:A B要連接到S,肯定首先A B雙方都會在本地創建一個socket,去連接S上的socket。創建一個socket必然會綁定一個本地端口(就算應用程序裏面沒寫端口,實際上也是 綁定了的,至少java確實如此),假設爲8888,這樣A和B才分別建立了到S的通信信道。接下來就需要打洞了,打洞則需要A和B分別發送數據包到對方 的公網IP。但是問題就在這裏:因爲NAT設備是根據端口號來確定session,如果是UDP的socket,A B可以分別再創建socket,然後將socket綁定到8888,這樣打洞就成功了。但是如果TCPsocket,則不能再創建socket並綁定到 8888了,這樣打洞就無法成功。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章