UDP 打洞示例 包含 服务器 客户端
客户端示例:
- #include "Net.h"
- #include "../p2pInfo.h"
- int main()
- {
- CUdp udp;
- if (0!=udp.Open(16888))
- {
- printf("client udp open failed \n");
- return -1;
- }
- P2P_CLIENT_INFO clientInfo;
- memset(&clientInfo,0,sizeof(P2P_CLIENT_INFO));
- clientInfo.nClientPort=16888;
- clientInfo.nID=0;
- sprintf(clientInfo.sClientIP,"%s","10.10.2.161");
- P2P_CMD_HEAD cmdHead;
- cmdHead.nCmd=P2P_CMD_REGISTER_REQ;
- cmdHead.nPayloadLen=sizeof(P2P_CLIENT_INFO);
- memcpy(cmdHead.sPayLoad,&clientInfo,sizeof(P2P_CLIENT_INFO));
- long lDestIP=0;
- CBSocket::ConvertStringToIP((int*)&lDestIP,"114.247.165.37");
- int nRet=0;
- nRet=udp.Send((unsigned char *)&cmdHead,CMD_HEAD_LEN+cmdHead.nPayloadLen,lDestIP,P2P_SERVER_PORT);
- printf("send register len %d \n",nRet);
- nRet=udp.Recv();
- if (nRet>0)
- {
- printf("recv data \n");
- }
- else
- {
- printf("recv P2P_CMD_REGISTER_ACK time out \n");
- return 0;
- }
- P2P_CLIENT_INFO remoteClientInfo;
- memset(&remoteClientInfo,0,sizeof(P2P_CLIENT_INFO));
- P2P_CMD_HEAD recvHead;
- memset(&recvHead,0,sizeof(P2P_CMD_HEAD));
- while (1)
- {
- cmdHead.nCmd=P2P_CMD_COMUNICATION_REQ;
- cmdHead.nValue=1; // remote id
- cmdHead.nPayloadLen=sizeof(P2P_CLIENT_INFO);
- nRet=udp.Send((unsigned char *)&cmdHead,CMD_HEAD_LEN+cmdHead.nPayloadLen,lDestIP,P2P_SERVER_PORT);
- printf("send commuication len %d \n",nRet);
- nRet=udp.Recv();
- if (nRet>0)
- {
- memcpy(&recvHead,udp.GetBuffer(),nRet);
- if (0==recvHead.nValue)
- {
- memcpy(&remoteClientInfo,recvHead.sPayLoad,sizeof(P2P_CLIENT_INFO));
- printf("recv P2P_CMD_COMUNICATION_ACK remote ip:%s port:%d\n",
- remoteClientInfo.sClientPublicIP,remoteClientInfo.nClientPublicPort);
- break;
- }
- usleep(100*1000);
- }
- else
- {
- printf("recv P2P_CMD_COMUNICATION_ACK time out \n");
- }
- }
- // send udp hole to remote ip
- CBSocket::ConvertStringToIP((int*)&lDestIP,remoteClientInfo.sClientPublicIP);
- cmdHead.nCmd=P2P_CMD_UDP_HOLE_REQ;
- cmdHead.nPayloadLen=0;
- udp.Send((unsigned char *)&cmdHead,CMD_HEAD_LEN,lDestIP,remoteClientInfo.nClientPublicPort);
- usleep(1000*1000);
- udp.Send((unsigned char *)&cmdHead,CMD_HEAD_LEN,lDestIP,remoteClientInfo.nClientPublicPort);
- usleep(1000*1000);
- udp.Send((unsigned char *)&cmdHead,CMD_HEAD_LEN,lDestIP,remoteClientInfo.nClientPublicPort);
- nRet=udp.Recv();
- if (nRet>0)
- {
- memcpy(&recvHead,udp.GetBuffer(),nRet);
- if (recvHead.nCmd==P2P_CMD_UDP_HOLE_ACK || recvHead.nCmd==P2P_CMD_UDP_HOLE_REQ)
- {
- printf("recv P2P_CMD_UDP_HOLE udp hole success\n");
- }
- }
- else
- {
- printf("P2P_CMD_UDP_HOLE recv out \n");
- return 0;
- }
- return 0;
- }
服务器端示例:
- #include "Net.h"
- #include "../p2pInfo.h"
- #define MAX_CLIENT_COUNT 16
- P2P_CLIENT_INFO* pClientList[MAX_CLIENT_COUNT];
- void AddClient(P2P_CLIENT_INFO* pClientInfo)
- {
- for(int i=0;i<MAX_CLIENT_COUNT;i++)
- {
- if (!pClientList[i])
- {
- P2P_CLIENT_INFO* pClient=new P2P_CLIENT_INFO;
- memcpy(pClient,pClientInfo,sizeof(P2P_CLIENT_INFO));
- pClientList[i]=pClient;
- return;
- }
- }
- }
- P2P_CLIENT_INFO* FindClient(int nID)
- {
- for(int i=0;i<MAX_CLIENT_COUNT;i++)
- {
- if (pClientList[i])
- {
- if (nID==pClientList[i]->nID)
- {
- return pClientList[i];
- }
- }
- }
- return NULL;
- }
- P2P_CLIENT_INFO* FindClient(long ip, unsigned short nPort)
- {
- for(int i=0;i<MAX_CLIENT_COUNT;i++)
- {
- if (pClientList[i])
- {
- int nIp=0;
- CBSocket::ConvertStringToIP(&nIp,pClientList[i]->sClientPublicIP);
- if (nPort==pClientList[i]->nClientPublicPort && ip==nIp)
- {
- return pClientList[i];
- }
- }
- }
- return NULL;
- }
- int main()
- {
- CUdp udp;
- udp.Open(P2P_SERVER_PORT);
- int nRet=0;
- P2P_CMD_HEAD* pCmdHead=new P2P_CMD_HEAD;
- P2P_CMD_HEAD* pSendCmdHead=new P2P_CMD_HEAD;
- memset(pCmdHead,0,sizeof(P2P_CMD_HEAD));
- memset(pSendCmdHead,0,sizeof(P2P_CMD_HEAD));
- long lRemoteIP=0;
- unsigned short nRemotePort=0;
- int i=0;
- for (i = 0; i <16; i++)
- {
- pClientList[i]=NULL;
- }
- while (1)
- {
- nRet=udp.Recv(lRemoteIP,nRemotePort);
- if (nRet>0)
- {
- memcpy(pCmdHead,udp.GetBuffer(),nRet);
- switch (pCmdHead->nCmd)
- {
- case P2P_CMD_REGISTER_REQ:
- {
- printf("recv register req \n");
- P2P_CLIENT_INFO* pClient=(P2P_CLIENT_INFO*)pCmdHead->sPayLoad;
- CBSocket::ConvertIPToString(lRemoteIP,pClient->sClientPublicIP);
- pClient->nClientPublicPort=nRemotePort;
- AddClient(pClient);
- printf("recv command P2P_CMD_REGISTER_REQ from ip:%s port:%d\n",pClient->sClientPublicIP,pClient->nClientPublicPort);
- pSendCmdHead->nCmd=P2P_CMD_REGISTER_ACK;
- pSendCmdHead->nPayloadLen=sizeof(P2P_CLIENT_INFO);
- memcpy(pSendCmdHead->sPayLoad,pClient,sizeof(P2P_CLIENT_INFO));
- udp.Send((unsigned char *)pSendCmdHead,CMD_HEAD_LEN+pSendCmdHead->nPayloadLen,lRemoteIP,nRemotePort);
- }
- break;
- case P2P_CMD_COMUNICATION_REQ:
- {
- printf("recv command P2P_CMD_COMUNICATION_REQ\n");
- P2P_CLIENT_INFO* pTargetClientInfo=FindClient(pCmdHead->nValue);
- if (!pTargetClientInfo)
- {
- printf("not find client info id:%d\n",pCmdHead->nValue);
- continue;
- }
- pSendCmdHead->nCmd=P2P_CMD_COMUNICATION_ACK;
- pSendCmdHead->nPayloadLen=sizeof(P2P_CLIENT_INFO);
- memcpy(pSendCmdHead->sPayLoad,pTargetClientInfo,sizeof(P2P_CLIENT_INFO));
- udp.Send((unsigned char *)pSendCmdHead,CMD_HEAD_LEN+pSendCmdHead->nPayloadLen,lRemoteIP,nRemotePort);
- // send to remote client
- int nIP=0;
- P2P_CLIENT_INFO* pSelfClientInfo=FindClient(lRemoteIP,nRemotePort);
- if (pSelfClientInfo)
- {
- printf("find self client info ip:%s\n",pSelfClientInfo->sClientPublicIP);
- memcpy(pSendCmdHead->sPayLoad,pSelfClientInfo,sizeof(P2P_CLIENT_INFO));
- CBSocket::ConvertStringToIP(&nIP,pTargetClientInfo->sClientPublicIP);
- udp.Send((unsigned char *)pSendCmdHead,CMD_HEAD_LEN+pSendCmdHead->nPayloadLen,nIP,pTargetClientInfo->nClientPublicPort);
- }
- else
- {
- printf("not find self client info");
- }
- }
- break;
- default:
- break;
- }
- }
- else
- {
- printf("udp recv time out \n");
- }
- }
- return 0;
- }
示例下载地址: http://download.csdn.net/detail/mtour/8119489
UDP 打洞示例 包含 服务器 客户端的更多相关文章
- c++下基于windows socket的服务器客户端程序(基于UDP协议)
前天写了一个基于tcp协议的服务器客户端程序,今天写了一个基于UDP协议的,由于在上一篇使用TCP协议的服务器中注释已经较为详细,且许多api的调用是相同的,故不再另外注释. 使用UDP协议需要注意几 ...
- UDP打洞、P2P组网方式研究
catalogue . NAT概念 . P2P概念 . UDP打洞 . P2P DEMO . ZeroNet P2P 1. NAT概念 在STUN协议中,根据内部终端的地址(LocalIP:Local ...
- UDP 打洞 原理解释
终于找到了一份满意的UDP打洞原理解释,附上正文,自己整理了一下源码 3.3. UDP hole punching UDP打洞技术 The third technique, and the one o ...
- udp打洞( NAT traversal )的方法介绍
http://www.cnblogs.com/whyandinside/archive/2010/12/08/1900492.html http://www.gzsec.com/oldversion/ ...
- UDP打洞原理及代码
来源:http://www.fenbi360.net/Content.aspx?id=1021&t=jc UDP"打洞"原理 1. NAT分类 根据Stun协议 ...
- Python实现简单的udp打洞(P2P)
UDP穿越NAT的具体设计 首先,Client A登录服务器,NAT 1为这次的Session分配了一个端口60000,那么Server S收到的Client A的地址是200.0.0.132:600 ...
- C# p2p UDP穿越NAT,UDP打洞源码
思路如下(参照源代码): 1. frmServer启动两个网络侦听,主连接侦听,协助打洞的侦听. 2. frmClientA和frmClientB分别与frmServer的主连接保持联系. 3. 当f ...
- QUdpSocket-Qt使用Udp通讯实现服务端和客户端
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QUdpSocket-Qt使用Udp通讯实现服务端和客户端 本文地址:https:// ...
- Udp打洞原理和源代码。
所谓udp打洞就是指客户端A通过udp协议向服务器发送数据包,服务器收到后,获取数据包,并且 可获取客户端A地址和端口号.同样在客户端B发送给服务器udp数据包后,服务器同样在收到B发送过来 的数据包 ...
随机推荐
- HDU——T 3342 Legal or Not
http://acm.hdu.edu.cn/showproblem.php?pid=3342 Time Limit: 2000/1000 MS (Java/Others) Memory Limi ...
- CodeForces 550E Brackets in Implications(构造)
[题目链接]:click here~~ [题目大意]给定一个逻辑运算符号a->b:当前仅当a为1b为0值为0,其余为1,构造括号.改变运算优先级使得最后结果为0 [解题思路]: todo~~ / ...
- 一种提高单片机i/o口驱动能力的方法
一.简述问题 当你用单片驱动发光二极管的时,你还感觉不到P0.P1口的差别.(10-20mA之间,当中P0驱动能力最强,但对于驱动直流电机依旧非常弱.其结果就是电机不转).那么有什么办法提高驱动能力吗 ...
- sp_executesql invalid object name
https://stackoverflow.com/questions/10417126/dynamically-named-temp-table-returns-invalid-object-nam ...
- thinkphp路由的作用
thinkphp路由的作用 问题 请问一下什么是thinkPHP路由,路由有什么作用?谢谢 解答 网络访问地址从来都是映射访问的,最初是这样,主机名(电脑名称)=>ip地址(如局域网192.16 ...
- Gym - 100625D Destination Unknown 最短路
http://codeforces.com/gym/100625/attachments/download/3213/2013-benelux-algorithm-programming-contes ...
- SQL 2008 还原 SQL2005 备份文件 不成功的解决方法
解决方法1:不要在数据库名字上点右键选择还原,而要是在根目录“数据库”三个字上点右键选择还原,然后再选择数据库,问题便可以解决,如果不行参照方法2 解决方法2:写sql语句处理: RESTORE DA ...
- 解决plsql遇到乱码的问题
遇到问题: PLSQL中汉字显示乱码,并且SQL语句中如果有汉字,则执行时报错.其实并不是SQL语句写的有问题,而是系统不能识别汉字. 解决方法. 首先执行语句 select * from V$NLS ...
- secureCRT 小技巧
破解: keygen.exe 放到安装目录下填好姓名公司 ,patch后generate就行了 连接问题: 连接出现socket error很有可能是你的防火墙没关,今天排查了很久才发现是这个问题,浪 ...
- JavaScript进阶之执行上下文和执行栈
js引擎的执行过程 执行上下文和执行栈属于js引擎的执行过程的预编译阶段. 执行上下文(Execution Context) 执行上下文是当前 JavaScript 代码被解析和执行时所在环境的抽象概 ...