1. 程式人生 > >UDT之P2P打洞大法

UDT之P2P打洞大法

終於打洞成功;算是費了九牛二虎之力了,走了不少彎路。不是UDT不好用,而是我思維混亂了。
總結一下吧,順便也方便一下還沒有打洞成功的同行。

第一個方案:
純用UDT來打洞,意思是不用UDP來先打洞,然後繫結UDT的方式。

                    Server C

       Client A                  Client B

1. A和B先建立一個UDT的Socket來連線伺服器,負責和Server C通訊。
簡稱 AA ,BB Socket。
   ----------------------------------------
   引數設定:AA 或者 BB = UDT.socket(AF_INET,SOCK_DGRAM,0)
             setsockopt UDT_REUSEADDR 為 True 
             bind(AA 或者 BB,local)
   ----------------------------------------

2.連線 ServerC
   AA,BB:
   UDT.connect(AA或者BB  ServerC)

3.B發起穿洞請求給Server C,ServerC獲取 B 的NAT IP和Port後發給 A:

                            Server C
                            /     ^\                        
                           /        \      
                          /          \ 
                        v/            \                  Client A            Client B

4. Client A收到訊息後,再返回給 Server C,讓C中轉給B自己的NAT IP和Port
   AA Send 
   
   Client A 開始建立2個Socket Sa 和 Sa' :
   -----------------------------------
    Sa Port = AA.Port
    socket(Sa..)  
    setsockopt(Sa, 0, UDT_MSS, new int(1052), sizeof(int));
    bind(Sa..)
    listen(Sa,..)
   -----------------------------------
   Sa' Port = AA.Port
   socket(Sa'..)
   setsockopt(Sa', 0, UDT_MSS, new int(1052), sizeof(int));
   bind(Sa'..)
   connect(Sa',B)

   用Sa來listen,用Sa'來連線B,當然這裡的連線是讓路由器建立個Session。

                             Server  C
                         /^     /      ^\   
                        /      /         \ 
                       /      /           \                        
                      /      /             \      
                     /      /               \ 
                    /     v/                 \                  Client A                     \                         Sa(listen)             \                         Sa'------>         Client B    

5. Clinet BB 收到 來自 來自CLient AA的經伺服器轉發的資訊後,建立一個
   新的Socket ,稱為 Sb
   ----------------------------------------
   Sb.Port = BB.Port
   socket(Sb..) 
   setsockopt Sb UDT_REUSEADDR 為 True 
   setsockopt(Sb, 0, UDT_MSS, new int(1052), sizeof(int)); 
   bind(Sb..)
   connect(Sb,AA)
   
                             Server  C
                         /^     /      ^\   
                        /      /         \ 
                       /      /           \                        
                      /      /             \      
                     /      /               \ 
                    /     v/                 \                  Client A                     \                         Sa(listen)         Client B 
                       
                         Sa'-------> 
                           <---------------Sb  
                           ---------------->

6.打洞成功 Sa' 和 Sb P2P通訊。

  可能還有細節上的錯誤,沒有來的及多測試。

------------------------------
第2個方案:用UDP來打洞,然後UDT設定 UDT_RENDEZVOUS來繫結打洞後的埠。

這個UDP打洞非常順利。但是由於bind(UDT,UDP)的時候出錯,程式報異常。測試終止。
有時間再好好看看是哪裡的原因吧。說明一下,我用的是Delphi寫的程式,udt.dll是自己
用C++Builder製作出來的。CVS上的原始碼我修改的地方也不多。也不是關鍵的程式碼。
想不出來是哪出的錯,所以,目前就放棄了。

原址:https://sourceforge.net/p/udt/discussion/852996/thread/38a28eaf/