`
750986570
  • 浏览: 2151 次
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

UDP to UDP 数据转发

C++ 
阅读更多
目的
    希望读者在阅读本文之前,已经读过了《『黑客编程』一、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;
}

分享到:
评论

相关推荐

    windows的udp端口转发工具sokit

    例如,将本地的5000端口的数据转发到远程服务器的6000端口,命令如下: ``` sokit forward udp 0.0.0.0:5000 remotehost:6000 ``` 在这个命令中,`0.0.0.0`表示监听所有网络接口,`remotehost`应替换为实际的...

    C#实现 TCP/UDP与串口之间相互转发通信,包含多个实例,有心跳过滤等

    C#实现 TCP/UDP与串口之间相互转发通信,包含多个实例,有心跳过滤等。包含串口之间相互转发。UDP与串口之间转发,TCP与串口之间相互转发。注释比较少,包含各种情况模拟事例,可自行参考相关描述。工程内包含多个...

    Delphi UDP 服务端和客服端发送数据测试程序.rar

    6. **防火墙和端口转发**:在实际部署时,要考虑防火墙设置,可能需要打开特定的端口以允许UDP通信。 7. **性能优化**:在大量数据传输或高并发场景下,优化UDP通信的性能是必要的,比如使用缓冲区管理和异步通信。...

    c# 实现的p2p UDP数据发送

    首先,我们来看标题中的"C#实现的P2P UDP数据发送"。这暗示我们需要创建两个关键部分:服务器端(P2PService)和客户端(P2PClient)。服务器端通常负责管理网络中的节点,而客户端则用于连接到服务器并与其他客户端...

    FPGA实现UDP协议栈,verilog语言附带说明

    FPGA实现的UDP模块需要能够根据这些信息进行正确的数据转发。 4. **用户接口**:这一部分是FPGA实现的UDP协议栈与应用交互的地方,提供接收和发送数据的接口。应用程序通过这些接口发送数据到特定的UDP端口,或者...

    监听指定端口的UDP信息

    在实际应用中,你可能还需要处理错误、添加日志记录、或者将接收到的数据转发到其他地方。此外,注意线程安全问题,特别是当多个线程同时访问UdpClient时。 以上就是使用C#监听指定端口的UDP信息的基本步骤。通过这...

    C++UDP服务器与客户端demo源码

    - `int sendto(SOCKET s, const char *buf, int len, int flags, const struct sockaddr *to, int tolen)` 发送数据。 - `int recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *...

    P2P(UDP穿越)

    5. **服务器辅助**:服务器作为中介,协调客户端的打洞过程,并在必要时转发数据。 通过研究这个源码,开发者可以深入了解P2P通信的底层机制,学习如何在NAT环境下实现UDP通信,这对于开发实时通信应用,如VoIP、...

    UDP千兆网传输FPGA代码 verilog

    - UDP发送模块:负责将上层应用数据封装成UDP数据报,并通过IP层发送出去。 - UDP接收模块:接收来自网络的UDP数据报,解封装后传递给上层应用。 - IP处理模块:处理IP头部,根据目的IP地址决定是否转发到UDP层。 - ...

    TCP/UDP打洞

    在UDP打洞中,一方主动向另一方的公共IP地址发送UDP数据包,如果对方所在的NAT设备支持UDP打洞,则会为该数据包创建一个临时的转发规则,从而允许数据包穿过NAT到达目标主机。 - **步骤**:首先,双方需要交换各自...

    用UDP协议实现NAT穿透

    NAT穿透,又称为P2P(Peer-to-Peer)穿透,是解决NAT环境下两个内网主机直接通信的技术,这对于多人在线游戏、VoIP、远程桌面等应用尤为重要。 NAT的工作原理是,当内部网络中的设备向外部发送数据时,NAT设备会将...

    udp tcp打洞测试.zip

    本篇将深入探讨UDP和TCP打洞测试,以及与之相关的P2P(Peer-to-Peer)、Vert.x和Kotlin技术。 首先,UDP是一种无连接的、不可靠的传输协议,它不保证数据包的顺序、完整性和到达。由于其轻量级特性,UDP常用于实时...

    基于UDP协议P2P通信技术的分析及实现

    UDP(User Datagram Protocol,用户数据报协议)是一种无连接的传输层协议,相比于TCP协议,UDP不保证数据包的可靠传输,也不提供流量控制和拥塞控制机制。尽管如此,UDP以其高效的数据传输能力,在实时通信场景中...

    UDP实现的NAT穿透

    UDP(User Datagram Protocol)是一种无连接的传输层协议,它提供了简单、快速的数据发送服务,但不保证数据的顺序或可靠性。在许多网络环境中,尤其是家庭宽带或公司网络,主机通常位于NAT(Network Address ...

    测试udp打洞

    标题中的“测试udp打洞”指的是利用UDP协议进行P2P(Peer-to-Peer)网络穿透技术的测试。P2P技术允许网络上的设备直接通信,而无需通过中心服务器,从而节省带宽并提高效率。UDP(User Datagram Protocol)是一种无...

    UDP协议进行P2P打洞

    UDP(User Datagram Protocol)协议是一种无连接的、不可靠的传输层协议,它在Internet协议族中扮演着重要角色,特别是在需要快速传输数据且对数据完整性要求不高的场景下。P2P(Peer-to-Peer)通信是互联网上的一种...

    据说能往内网广播的udp程序

    标题“据说能往内网广播的udp程序”和描述中提到的关键词是“UDP”和“公网IP”,这涉及到网络通信中的用户数据报协议(UDP)以及内网穿透技术。以下将详细介绍这两个知识点: **用户数据报协议(UDP)** UDP是一种...

    Lwip之UDP实现.pdf

    初始化时,还会为TTL(Time To Live,生存时间)字段赋值为`UDP_TTL`(通常设为255),这是UDP数据报在网络中可以转发的最大跳数。 #### Udp_remove:移除UDP PCB `Udp_remove`函数的功能是将指定的UDP PCB从`udp_...

    qt udp学习文档.docx

    在Qt中,QUdpSocket类提供了发送和接收UDP数据报的功能。使用QUdpSocket,开发者可以通过绑定特定的IP地址和端口来实现数据的接收,通过writeDatagram()方法向指定的IP地址和端口发送数据。 二、UDP通信模式 1. 单...

    udp_P2P即时视频文件传输+视频

    数据交换通常采用洪泛或逐跳转发策略。 3. **视频编码与解码**:视频文件传输前,通常需要先进行编码以减小传输体积,常见的编码格式有H.264、VP9等。C#中可以使用开源库如FFmpeg来处理视频编码和解码。 4. **实时...

Global site tag (gtag.js) - Google Analytics