前天編程做了一下UDP打洞的實驗,今天特寫了一篇文章總結(jié)一下。
我們知道網(wǎng)絡(luò)上兩個主機(jī)進(jìn)行通信,如果其中一臺主機(jī)擁有公網(wǎng)IP那么,那么進(jìn)行會話是比較簡單的,但是如果兩臺主機(jī)是位于不同內(nèi)網(wǎng)之中的,那么應(yīng)該如何進(jìn)行通信呢。一種想法是再找一臺公網(wǎng)的服務(wù)器,用來轉(zhuǎn)發(fā)信息,但是這有一個問題,就是會給服務(wù)器帶來壓力,因此我們就來談?wù)勔环N用于不同內(nèi)網(wǎng)中的主機(jī)互相通信的一個解決方案——NAT打洞。
原理還是比較簡單的,我們先了解一下什么是“NAT的洞”。當(dāng)處于內(nèi)網(wǎng)中的一臺主機(jī)(ClientA/192.168.1.128)向一個公網(wǎng)的服務(wù)器(Server)發(fā)送數(shù)據(jù)時,這時NAT(NAT1)將會打開一個臨時性的端口用于與公網(wǎng)的服務(wù)器進(jìn)行通信,并且會把那個內(nèi)網(wǎng)主機(jī)發(fā)送出的IP數(shù)據(jù)報的頭部中源IP地址改為NAT的公網(wǎng)IP(218.7.32.28),將TCP或UDP數(shù)據(jù)報中源端口(2347)改為那個臨時端口(26756)這樣就實現(xiàn)了由“192.168.1.128:2347”到“218.7.32.28:26756”的源地址源端口的轉(zhuǎn)換。這個數(shù)據(jù)包到達(dá)公網(wǎng)服務(wù)器后,服務(wù)器就可以根據(jù)這個包的頭部信息進(jìn)行回復(fù)。當(dāng)服務(wù)器的數(shù)據(jù)包到達(dá)NAT后,NAT在將這個數(shù)據(jù)發(fā)送到內(nèi)網(wǎng)主機(jī)192.168.1.128的2347端口。那么這個NAT上的26756端口我們就稱作“洞”。如果這個NAT不是Full Cone NAT的話(其實大多數(shù)的NAT確實不是這種類型的),那么我們說這個“洞”是有方向性的。一個洞應(yīng)該會指向一個(也可以是多個)公網(wǎng)主機(jī)的IP地址。比如上面說的例子,在NAT1上打的洞是指向Server的IP地址。來自其他公網(wǎng)主機(jī)發(fā)向這個洞(也就是218.7.32.28:26756)的數(shù)據(jù)包會被非Full Cone類型的NAT所丟棄。所以如果有另一臺處于另一內(nèi)網(wǎng)的主機(jī)(ClientB/192.168.0.5)向218.7.32.28:26756直接發(fā)送數(shù)據(jù)的話,同樣也會被NAT1丟棄。
那么如何建立ClientA和ClientB的直接會話呢?
網(wǎng)絡(luò)環(huán)境描述:
內(nèi)網(wǎng)1NAT:NAT1/218.7.32.28
內(nèi)網(wǎng)1中一臺主機(jī):ClientA/192.168.1.128
內(nèi)網(wǎng)2NAT:NAT2/218.7.31.221
內(nèi)網(wǎng)2中一臺主機(jī):ClientB/192.168.0.5
公網(wǎng)服務(wù)器:Server
首先讓ClientA和ClientB登錄到服務(wù)器Server(假如兩臺主機(jī)都采用2347端口),此時NAT1和NAT2會分別為ClientA和ClientB打開一個指向Server的洞(NAT1上218.7.32.28:26756和NAT2上218.7.31.221:27550)。服務(wù)器應(yīng)改記錄這兩個客戶端的信息(關(guān)鍵是那兩個洞的信息)。當(dāng)ClientA與ClientB要建立會話時,ClientA首先用2347端口向NAT2的洞發(fā)送一個數(shù)據(jù)包,當(dāng)然這個數(shù)據(jù)包會被NAT2所丟棄,但是由于這是從NAT1內(nèi)部向外部發(fā)送數(shù)據(jù),所以NAT1為ClientA打開了一個指向NAT2的洞。而且這個新洞與原來NAT1上指向Server的舊洞的是同一個洞(因為是同一個端口26756),所以這里可以說這個洞具有了兩個方向,同時指向Server和NAT2。這時ClientA應(yīng)該通知Server,告訴ClientB,現(xiàn)在可以向NAT1的那個洞(218.7.32.28:26756)發(fā)送數(shù)據(jù)包了。當(dāng)ClientB向NAT1的那個洞發(fā)送數(shù)據(jù)以后,NAT2也為ClientB打了一個指向NAT1的洞,這是可以說ClientA與ClientB的會話就建立完成了,他們可以不依賴Server進(jìn)行通信了。如果以后ClientA和ClientB還需要建立其他會話 ,那么這個牽線的“媒人”可以不是Server,而可以是ClientA或ClientB了。
UDP打洞可以實現(xiàn)不同內(nèi)網(wǎng)內(nèi)的主機(jī)進(jìn)行通信,而且實施性比較高,一般用于P2P通信。這也就是為什么常會看見騰訊QQ在開始傳輸文件時會顯示“UDP連接已經(jīng)建立”了。
該文章在 2014/1/26 14:22:38 編輯過