利用UDX进行P2P文件传输,UDP可靠文件传输

来源:互联网 发布:ubuntu jenkins 卸载 编辑:程序博客网 时间:2024/05/02 00:50

关健字:

UDP

UDT

UDX

UDP文件传输

NAT,P2P,穿透

 

实现:

如今P2P NAT技术已经是比较成熟的技术,在网上也有很详细的原理及实现,但是,真正能稳定使用的代码却很少.或者是参数设置复杂,代码庸长,不便于项目实施.

UDX是一个比较方便使用的UDP库,可以利用接口简单设置,P2P服务器参数,超时,就可以完成P2P联接,让应用程序开发变得相当简单,我现在就UDX样例程中的P2PSENDFILE工程分析一下,主要的几个步骤.

 

1.设置P2P回调函授,这样,当P2P成功或超时时我们能得到通知.

代码片段1:

class CP2pSendFileDlg : public CDialog,
 public IUdxFSink,//当有对方请求发送文件时,触发相关事件
 public IUdxP2pSink,//当P2P事件发生回调
 public ITransFormSink//当P2P不成功时,中转事件接口
{
我们把主界面,从这些接口派生,这样,可以接收到UDX内部发出的一些事件,这些事件是由UDX内部线程回调的.

别忘了关健的一部设置,回调关联,把UDX和我们的主界面关联起来.利用UDX的接口SetSink

 

2,设置P2P参数,进行P2P

代码片段2:

void CP2pSendFileDlg::OnButton2()
{

 IUdxP2pClient * pP2pClient = m_pFileSend->GetP2pClient();//从UDX接口中查询到P2P接口
 pP2pClient->SetNatServer(m_strP2pSver.GetBuffer(0),m_port);//设置 P2P 打洞中介服务器
 pP2pClient->SetSink(this);//和主界面关联,关健,不然收不到UDX P2P成功的消息 了.
 pP2pClient->Start();//开始进行P2P

 if(pP2pClient->ConnectServer(m_userid.GetBuffer(0),m_desuserid.GetBuffer(0),(DWORD)this))//对用户1和用户2组成的字符串对进行P2P,并可以设置回调时的参数
 {
 } 

 

3,处理P2P结果

一切准备就绪,当P2P发生时会做哪些事情呢?我们再来看代码

代码片段3

void CP2pSendFileDlg::OnP2pConnect( SOCKADDR addrRemote,int errocode,char* user1,char* user2,DWORD dwuser )
{//回调中有五个参数,分别是应用层比较关心的几个值 ,分别是,对方外网地址,错误码,用户1,用户2,进行P2P时协带的用户自定义指针


 sockaddr_in *pAddr = (sockaddr_in*)&addrRemote; 
 char*ip = inet_ntoa(pAddr->sin_addr);
 UDP_SHORT port = ntohs(pAddr->sin_port) ;
 if(errocode == 0)//如果P2P成功,如果是发送端,就直联P2P成功的地址,因为已经被我们"打洞成功",所以,可以直接联接了
 {   
  if(m_bSender) 
  {
   if(m_pFileSend->Connect(ip,port,TRUE))//阻塞联接
   {

    m_pFileSend->SendFile(m_strFileName.GetBuffer(0));

   }
   SetTimer(101,1000,0);  
  }else
  {
   SetTimer(100,1000,0);
  }
  AfxGetMainWnd()->SetWindowText("p2p 成功");
 }else//如果P2P不成功,转入中转模式,形式如何P2P过程
 {
  AfxGetMainWnd()->SetWindowText("p2p erro!");
  if(m_bSender)
  {
   ITransFormClient * pTransFormClient = m_pFileSend->GetITransFormClient();//得到UDX的中转接口
   pTransFormClient->AddMiddleServer(m_strMiddleSver.GetBuffer(0),2200);//设置中转服务器,可以设置多个
   pTransFormClient->SetSink(this);//设置回调
   pTransFormClient->RegisterClient(m_userid.GetBuffer(0), m_desuserid.GetBuffer(0),(DWORD)this);//注册中转用户对
   pTransFormClient->Start();//开始注册

  }else
  {
   ITransFormClient * pTransFormClient = m_pFileRecive->GetITransFormClient();
   pTransFormClient->AddMiddleServer(m_strMiddleSver.GetBuffer(0),2200);
   pTransFormClient->SetSink(this);
   pTransFormClient->RegisterClient(m_userid.GetBuffer(0), m_desuserid.GetBuffer(0),(DWORD)this);
   pTransFormClient->Start();
  }

 }
}

 

4,处理中转结果

中转回调事件

代码片段4:

void CP2pSendFileDlg::OnRegister(int errcode,DWORD streamid,char *user1,char* user2,DWORD dwUser)
{//UDX提供了五个参数,分别是错误码,流ID,用户1,用户2,及用户自定义数据
 if(errcode != 0)  
 {
  AfxGetMainWnd()->SetWindowText("OnRegister erro!");
  return;
 }

 if(m_bSender) 
 {
  m_pFileSend->SetTransformMSID(streamid);
  if(m_pFileSend->Connect("127.0.0.1",1024,TRUE))//当注册成功时,联接的IP,PORT是任意的,可以忽略,随便什么都可以.
  {   
   m_pFileSend->SendFile(m_strFileName.GetBuffer(0));
   
   AfxGetMainWnd()->SetWindowText("发送中转成功");
  }
  SetTimer(101,1000,0);  
 }else
 {
  m_pFileRecive->SetTransformMSID(streamid);
  SetTimer(100,1000,0);
  AfxGetMainWnd()->SetWindowText("接收端中转成功");
 }
 
}

运行结果

http://hi.csdn.net/attachment/201101/25/0_12959179993YNr.gif

 

以上代码可以在这里下載得到

http://www.goodudx.com/web/index.php/site/download/19