UDP to TCP 数据转发 .

提供UDP客户端到TCP服务器的访问的数据转发。有时候我们的服务器提供TCP的数据包格式,可是由于种种原因,我们的客户端只能通过UDP来访问。本文就是提供UDP到TCP的数据转发的功能。本代理接收UDP客户连接请求后,把数据转发到TCP服务器,同时把TCP服务器回送的数据,转发回UDP客户。

设计

//主程序
Main()
{
   beginthread(u2tMainThread());
}

//主线程
u2tMainThread(Param)
{
   while(true)
   {
      创建"本地接收 UDP SOCK"
      while(read  >0)
      {
         等待 UDP 数据包
  收到数据后,查找"目标 TCP SOCK"
  if(没有找到)
  {
      创建一个新的"目标 TCP SOCK"
     "目标 TCP SOCK"连接成功后,创建"u2t wait thread"
  }
  通过"目标 TCP SOCK"发送数据
      }
   }
}

//t2u Wait Thread 线程 
u2t Wait Thread (Param)
{
   创建"目标 TCP SOCK"->"连接 UDP SOCK"数据转发Thread
   等待线程结束
   释放SOCK资源
}

//TCP2UDP 数据转发线程
TCP2UDP Thread(Param)
{
   SOCK FROM,TO
   while(read  >0)
   {
 read(From,Buff);
 Sendto(To,Buff);
   }
}


参考代码


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

//主线程
DWORD u2tmainthread(LPVOID lpvoid)
{
 AGENTTCPUDPGATEWAYINFO *pasi = (AGENTTCPUDPGATEWAYINFO*)lpvoid;
 AGENTTCPUDPGATEWAYINFO asi;
 memcpy(&asi,pasi,sizeof(AGENTTCPUDPGATEWAYINFO));
 delete pasi; pasi = NULL;
//-t

 //如果模式为u2t,那么此地址结构是UDP Client的地址,此地址在接收到UDP Client数据后填充

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

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

 //监听本地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************Udp2Tcp Start new**************/n/n");
  _DelSock(s[0]);
  //创建一个UDP socket
  s[0]=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
  if(s[0]==INVALID_SOCKET)
  {
   ShowError("/nUdp2Tcp:Create UDP socket");
   Sleep(5000);
   continue;
  }
  //bind UDP socket
  iRet=bind(s[0],(struct sockaddr *)&UDPLocal,sizeof(UDPLocal));
  if(iRet == SOCKET_ERROR)
  {
   printf("/nUdp2Tcp:Bind UDP port %d failed.",asi.LocalPort);
   Sleep(5000);
   continue;
  }
  else
   printf("/nUdp2Tcp: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)
   {
    //然后才TCP connect到Target监听的TCP Port
    //创建一个TCP socket
    s[1]=socket(AF_INET,SOCK_STREAM,IPPROTO_IP);
    if(s[1]==INVALID_SOCKET)
    {
     ShowError("/nUdp2Tcp:Create TCP socket");
     Sleep(5000);
     continue;
    }
    //connect to Target
    while(1)
    {
     iRet=connect(s[1],(SOCKADDR *)&Target,sizeof(Target));
     if(iRet!=0)
     {
      printf("/nUdp2Tcp:Connect to Target TCP %s:%d failed.Wait for try again.",asi.TargetIP,asi.TargetPort);
      Sleep(1000);
     }
     else
     {
      printf("/nUdp2Tcp:Connent to Target TCP %s:%d ok.",asi.TargetIP,asi.TargetPort);
      break;
     }
    }
    DATAREDIRDPARAM* ptdataredird = new DATAREDIRDPARAM;
    ptdataredird->sock[0] = s[0];//udp
    ptdataredird->sock[1] = s[1];//tcp
    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,u2twaitthread,(LPVOID)ptdataredird2,NULL,&threadid);
    CloseHandle(htcp2udpThread);
   }
   printf("/ntUdp2Tcp: recvfrom %d bytes.",read);
   int npos=0;
   while(npos < read)
   {
    int nsendcount = send(s[1],incomingbuff+npos,read-npos,0);
    if(nsendcount <= 0 )
    {
     udpsvrDelDataRedird(s[1]);
     break;
    }
    printf("/ntUdp2Tcp: send %d bytes.",nsendcount);
    npos += nsendcount;
   }
  }
  udpsvrDelAllDataRedird(s[0]);
  printf("/n/n**************OK!Udp2Tcp do next******************/n/n");
 }//end of while
 if(sListen!=INVALID_SOCKET) closesocket(sListen);
 return 0;
}
DWORD u2twaitthread(LPVOID lpvoid)
{
 DATAREDIRDPARAM* pdrp = (DATAREDIRDPARAM*)lpvoid;
 HANDLE hThread;
 DWORD id;
 hThread = CreateThread(NULL,0,tcp2udp,(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;
}

//tcp 2 udp 代码
//从sock[1]=>TCP socket读
//往sock[0]=>UDP socket写
DWORD  tcp2udp(LPVOID lpvoid)
{
 DATAREDIRDPARAM *tudp = (DATAREDIRDPARAM*)lpvoid;
 SOCKET *s = tudp->sock;

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

 char incomingbuff[maxsize];
 int read = 1;

 int iUDPRepeat=3;//UDP发送失败后重复的次数
 while(read  >0)
 {
  read  = recv(s[1],incomingbuff, maxsize,0);
  if(read <=0  ) break;
  printf("/nTCP2UDP Thread %d recv %d bytes.",threadid,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("/nTry %d times to send.",iUDPRepeat);
     continue;
    }
   }
   if(nsendcount <= 0 ) return 0;
   printf("/nTCP2UDP[%d] sendto %s:%d %d bytes.",threadid,inet_ntoa(tudp->sinudp.sin_addr),ntohs(tudp->sinudp.sin_port),nsendcount);
   npos += nsendcount;
  }
 }
 printf("/nTCP2UDP %d LastError %d",threadid,GetLastError());
 return 0;
}

你可能感兴趣的:(UDP to TCP 数据转发 .)