查看單個文章
舊 2005-06-15, 05:23 AM   #3 (permalink)
psac
榮譽會員
 
psac 的頭像
榮譽勳章
UID - 3662
在線等級: 級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時級別:30 | 在線時長:1048小時 | 升級還需:37小時
註冊日期: 2002-12-07
住址: 木柵市立動物園
文章: 17381
現金: 5253 金幣
資產: 33853 金幣
預設

此時,Client A與Client B都可以與Server S通信了。如果Client A此時想直接傳送訊息給Client B,那麼他可以從Server S那兒獲得B的公共外網位址187.34.1.56:40000,是不是Client A向這個位址傳送訊息Client B就能收到了呢?

答案是不行,因為如果這樣傳送訊息,NAT B會將這個訊息丟棄(因為這樣的訊息是不請自來的,為了安全,大多數NAT都會執行丟棄動作)。現在我們需要的是在NAT B上打一個方向為202.187.45.3(即Client A的外網位址)的洞,那麼Client A傳送到187.34.1.56:40000的訊息,Client B就能收到了。這個打洞指令由誰來發呢,哈哈,當然是Server S。


總結一下這個程序:如果Client A想向Client B傳送訊息,那麼Client A傳送指令給Server S,請求Server S指令Client B向Client A方向打洞。

哈哈,是不是很繞口,不過沒關係,想一想就很清楚了,何況還有來源碼呢(侯老師說過:在來源碼面前沒有秘密 8)),然後Client A就可以通過Client B的外網位址與Client B通信了。

注意:以上程序只適合於Cone NAT的情況,如果是Symmetric NAT,那麼當Client B向Client A打洞的連接阜已經重新分配了,Client B將無法知道這個連接阜(如果Symmetric NAT的連接阜是順序分配的,那麼我們或許可以猜測這個連接阜號,可是由於可能導致失敗的因素太多,我們不推薦這種猜測連接阜的方法)。

下面是一個模擬P2P聊天的程序的來源碼,程序很簡單,P2PServer執行在一個擁有公共外網IP的電腦上,P2PClient執行在兩個不同的NAT後(注意,如果兩個客戶端執行在一個NAT後,本程序很可能不能執行正常,這取決於你的NAT是否支持loopback translation,詳見http://midcom-p2p.sourceforge.net/draft-ford-midcom-p2p-01.txt,當然,此問題可以通過雙方先嘗試連接對方的局內網IP來解決,但是這個程式碼只是為了驗證原理,並沒有處理這些問題),後登入的電腦可以獲得先登入電腦的用戶名,後登入的電腦通過send username message的格式來傳送消息。

如果傳送成功,說明你已取得了直接與對方連接的成功。
程序現在支持三個指令:send , getu , exit

send格式:send username message
功能:傳送訊息給username

getu格式:getu
功能:獲得當前伺服器用戶列表

exit格式:exit
功能:註銷與伺服器的連接(伺服器不會自動監測客戶是否吊線)

程式碼很短,相信很容易懂,如果有什麼問題,可以給我發郵件zhouhuis22@sina.com 或者在CSDN上傳送短消息。同時,歡迎轉發此文,但希望保留作者版權8-)。

最後感謝CSDN網友 PiggyXP 和 Seilfer的測試說明
__________________
http://bbsimg.qianlong.com/upload/01/08/29/68/1082968_1136014649812.gif
psac 目前離線  
送花文章: 3, 收花文章: 1631 篇, 收花: 3205 次