UDP to UDP 数据转发

来源:互联网 发布:淘宝购买战网点 编辑:程序博客网 时间:2024/06/01 10:14

目的
    希望读者在阅读本文之前,已经读过了《『黑客编程』一、TCP to TCP 数据转发》,UDP to UDP可以用作QQ通过转发代理聊天的功能。
应用机器A,提供UDP端口的服务,转发代理机器B,提供UDP转发端口服务,客户机C通过UDP把数据发送到B,B再转发给A,并把A发送的数据转发
给C。

设计
//主程序
Main()
{
   beginthread(u2uMainThread());
}

//主线程
u2uMainThread(Param)
{
   while(true)
   {
      创建"本地接收数据SOCK",用来接收并转发客户端C发送过来的数据
      while(read>0)
      {
         等待并接收客户端C数据
  等到后,查找"目标SOCK"
  if(没有找到)
  {
      创建一个新的"目标SOCK"
     "目标SOCK"创建成功后,创建"Wait Thread",
  }
  用"目标SOCK"发送数据到应用A
      }
   }
}
//Wait 线程 
Wait Thread(Param)
{
  创建"目标SOCK"->"连接SOCK"数据转发Thread
  等待这个线程结束
  释放SOCK资源
}
//TCP2TCP数据转发线程
UDP2UDP Thread(Param)
{
   SOCK FROM,TO
   while(read  >0)
   {
 readfrom(From,Buff);
 Sendto(To,Buff);
   }
}

参考代码
参数结构
struct AGENTTCPUDPGATEWAYINFO
{
 char TargetIP[40];
 int TargetPort;
 int LocalPort;
 int LocalTmpPort;
};

//主线程
DWORD WINAPI  u2umainthread(LPVOID lpvoid)
{
 //获取参数
 AGENTTCPUDPGATEWAYINFO *pasi = (AGENTTCPUDPGATEWAYINFO*)lpvoid;
 AGENTTCPUDPGATEWAYINFO asi;
 memcpy(&asi,pasi,sizeof(AGENTTCPUDPGATEWAYINFO));
 delete pasi; pasi = NULL;
//-b

 int iRet;
 struct sockaddr_in UDPLocal,Target;
 SOCKET s[2];//s[0]=>UDP socket s[1]=>TCP socket
 HANDLE hThread[2]={NULL,NULL};

 printf("/nOK!Work mode is udp2udp.");

 //监听本地UDP port的地址结构
 UDPLocal.sin_family=AF_INET;
 UDPLocal.sin_addr.s_addr=INADDR_ANY;
 UDPLocal.sin_port=htons(asi.LocalPort);
 //目标地址结构
 Target.sin_family=AF_INET;
 Target.sin_addr.s_addr=inet_addr(asi.TargetIP);
 Target.sin_port=htons(asi.TargetPort);
 //开始循环
 while(1)
 {
  printf("/n/n************Udp2Udp Start new**************/n/n");
  _DelSock(s[0]);
  //创建一个UDP socket
  s[0]=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
  if(s[0]==INVALID_SOCKET)
  {
   ShowError("/nUdp2Udp:Create UDP socket");
   Sleep(5000);
   continue;
  }
  _AddSock(s[0]);
  //bind UDP socket
  iRet=bind(s[0],(struct sockaddr *)&UDPLocal,sizeof(UDPLocal));
  if(iRet == SOCKET_ERROR)
  {
   printf("/nUdp2Udp:Bind UDP port %d failed.",asi.LocalPort);
   Sleep(5000);
   continue;
  }
  else
   printf("/nUdp2Udp:Bind UDP port %d ok.",asi.LocalPort);

//  DWORD threadid=GetCurrentThreadId();
  struct sockaddr_in from;
  int dwSize=sizeof(from);
  char incomingbuff[maxsize];
  int read = 1;
  while(read  >0)
  {
   read=recvfrom(s[0],incomingbuff,maxsize,0,(SOCKADDR *)&from,&dwSize);
   if(read <=0  ) break;
   s[1] = udpsvrGetSock1(from) ;
   if(s[1] == 0)
   {
    //创建一个UDP socket
    s[1]=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
    if(s[1]==INVALID_SOCKET)
    {
     ShowError("/nTcp2Udp:Create UDP socket");
     Sleep(5000);
     continue;
    }
    BOOL bindok = FALSE;
    int LocalTmpPort = asi.LocalTmpPort;
    if(LocalTmpPort<1) LocalTmpPort = 4000;
    while(LocalTmpPort <65535)
    {
     //监听本地UDP port的地址结构
     UDPLocal.sin_family=AF_INET;
     UDPLocal.sin_addr.s_addr=INADDR_ANY;
     UDPLocal.sin_port=htons(LocalTmpPort);
     //bind UDP socket
     iRet=bind(s[1],(struct sockaddr *)&UDPLocal,sizeof(UDPLocal));
     if(iRet == SOCKET_ERROR)
     {
      printf("/nTcp2Udp:Bind UDP port %d failed.",LocalTmpPort);
      LocalTmpPort ++ ;
      Sleep(50);
      continue;
     }
     else
     { 
      printf("/nTcp2Udp:Bind UDP port %d ok.",LocalTmpPort);
      bindok = TRUE;
      break;
     }
    }
    if(!bindok)
    {
     _DelSock(s[0]);
     _DelSock(s[1]);
     Sleep(5000);
     continue;
    }

    DATAREDIRDPARAM* ptdataredird = new DATAREDIRDPARAM;
    ptdataredird->sock[0] = s[0];//udp
    ptdataredird->sock[1] = s[1];//udp
    memcpy(&ptdataredird->sinudp ,&from,sizeof(sockaddr_in));
    ptdataredird->sinudpisfilled = TRUE;
    udpsvrAddDataRedird(ptdataredird);
    DATAREDIRDPARAM* ptdataredird2 = new DATAREDIRDPARAM;
    memcpy(ptdataredird2,ptdataredird,sizeof(DATAREDIRDPARAM));
    DWORD threadid;
    HANDLE htcp2udpThread = CreateThread(NULL,0,u2uwaitthread,(LPVOID)ptdataredird2,NULL,&threadid);
    CloseHandle(htcp2udpThread);
   }
   printf("/ntUdp2Tcp: recvfrom %s:%d %d bytes.",inet_ntoa(from.sin_addr),ntohs(from.sin_port),read);
   int iUDPRepeat = 3;
   int npos=0;
   while(npos < read)
   {
    int nsendcount=sendto(s[1],incomingbuff+npos,read-npos,0,(SOCKADDR *)&Target,sizeof(Target));
    if(nsendcount == SOCKET_ERROR)
    {
     ShowError("sendto");
     //重复发送次数自减一
     if((iUDPRepeat--)>0)
     {
      printf("/nUDP2UDP Try %d times to send.",iUDPRepeat);
      continue;
     }
    }
    if(nsendcount <= 0 ) return 0;
    printf("/nUDP2UDP:sendto %s:%d %d bytes.",inet_ntoa(Target.sin_addr),ntohs(Target.sin_port),nsendcount);
    npos += nsendcount;
   }
  }
  udpsvrDelAllDataRedird(s[0]);
  printf("/n/n**************OK!Udp2Tcp do next******************/n/n");
 }//end of while
 return 0;
}
//监护线程
DWORD WINAPI u2uwaitthread(LPVOID lpvoid)
{
 DATAREDIRDPARAM* pdrp = (DATAREDIRDPARAM*)lpvoid;
 HANDLE hThread;
 DWORD id;
 hThread = CreateThread(NULL,0,udp2udp,(LPVOID)pdrp,NULL,&id);
 _AddThread(hThread);
 DWORD  waiter;
 waiter = WaitForSingleObject(hThread,INFINITE);
 udpsvrDelDataRedird(pdrp->sock[1]);
 _DelThread(hThread);
 printf("/nUdp2Tcp: Socket closed./n");
 delete pdrp;
 ExitThread(0);
 return 0;
}
//
//UDP socket数据转发函数,从s[0]接收数据,转发到s[1]
//
DWORD WINAPI udp2udp(LPVOID lpvoid)
{
 DATAREDIRDPARAM *tudp = (DATAREDIRDPARAM*)lpvoid;
 SOCKET *s = tudp->sock;

 DWORD threadid=GetCurrentThreadId();
 printf("/n***New UDP2UDP Thread %d recvfrom %d sendto %d./n",threadid,s[1],s[0]);

 struct sockaddr_in from;
 int dwSize=sizeof(from);
 int iUDPRepeat=3;//UDP发送失败后重复的次数

 char incomingbuff[maxsize];
 int read = 1;
 while(read  >0)
 {
  read=recvfrom(s[1],incomingbuff,maxsize,0,(SOCKADDR *)&from,&dwSize);
  if(read <=0  ) break;
  printf("/nUDP2UDP[%d] recvfrom %s:%d %d bytes.",threadid,inet_ntoa(from.sin_addr),ntohs(from.sin_port),read);
  iUDPRepeat = 3;
  int npos=0;
  while(npos < read)
  {
   int nsendcount=sendto(s[0],incomingbuff+npos,read-npos,0,(SOCKADDR *)&tudp->sinudp,sizeof(tudp->sinudp));
   if(nsendcount == SOCKET_ERROR)
   {
    ShowError("sendto");
    //重复发送次数自减一
    if((iUDPRepeat--)>0)
    {
     printf("/nUDP2UDP Try %d times to send.",iUDPRepeat);
     continue;
    }
   }
   if(nsendcount <= 0 ) return 0;
   printf("/nUDP2UDP[%d] sendto %s:%d %d bytes.",threadid,inet_ntoa(tudp->sinudp.sin_addr),ntohs(tudp->sinudp.sin_port),nsendcount);
   npos += nsendcount;
  }
 }
 printf("/nUDP2UDP Thread %d LastError %d",threadid,GetLastError());
 return 0;
}

 
原创粉丝点击