浏览 2998 次
锁定老帖子 主题:UDP to UDP 数据转发
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-09-26
希望读者在阅读本文之前,已经读过了《『黑客编程』一、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; } 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |