首页 > 编程知识 正文

怎么打孔,机制本是什么

时间:2023-05-04 17:23:49 阅读:115437 作者:1373

什么是打洞

假设有两个按钮a、b,什么是开孔。 他们的通信需要通过腾讯的服务器。 也就是说,a要向b发送消息,必须先在腾讯服务器上传输一次,然后再去b那里。 但是,在视频通话等要求实时性的通信中,这种方式无法保证他们通信的实时性。 如果能想办法让他们直接通信的话,实时性会相当高。 但是,我们知道的路由器有保护机制,a和b要通信,必须熟悉所拥有的数据包的IP,所以这时需要在两个路由器之间开孔,但这件事牵涉到腾讯。

简而言之,我们登录按钮后,就会访问腾讯服务器。 腾讯服务器也将数据包返回。 此数据包携带与服务器公共网络腾讯的IP。 相反,服务器的公共网络IP在a、b中是众所周知的IP。 然后,服务器利用公共网络IP帮助a、b打洞。 打洞是实现通道。 打开此孔后,A、b由服务器完成打孔,最终目的是提高数据传输的效率。 UDP打孔 所谓udp打洞就是指客户端A通过udp协议向服务器发送数据包,服务器收到后,获取数据包,并且可获取客户端A地址和端口号。同样在客户端B发送给服务器udp数据包后,服务器同样在收到B发送过来的数据包后获取B的地址和端口号,将A和B的地址与端口号分别发送给对方,这样双方可以继续用UDP协议通信。这么做有什么用呢?因为对于一些应用或者需求,需要两个客户端临时做一些通信,而这种通信不需要建立tcp就可以完成,所以才去udp打洞。

以下是以前写的服务器代码

int main() { listsockaddr_in addrList; int sockServer = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sockServer == -1) { printf("socket server failed. errno = [%d]n", errno); return -2; } struct sockaddr_in addrServer = { 0 }; addrServer.sin_family = AF_INET; addrServer.sin_addr.s_addr = INADDR_ANY; addrServer.sin_port = htons(10000); if (bind(sockServer, (struct sockaddr *)addrServer, sizeof(addrServer)) != 0) { printf("bind server faile errno = [%d]n", errno); return -3; } while (1) { char content[10240] = { 0 }; struct sockaddr_in addrUser1 = { 0 }; socklen_t u1Len = sizeof(addrUser1); if (recvfrom(sockServer, content, sizeof(content), 0, (struct sockaddr *)addrUser1, u1Len) == -1) { printf("recv user 1 failed. errno = [%d]n", errno); return -4; } else { printf("connect user ip = [%s] port = [%d]n", inet_ntoa(addrUser1.sin_addr), htons(addrUser1.sin_port)); if (addrList.size()) { struct sockaddr_in peerAddr = addrList.front(); int addrLen = sizeof(peerAddr); printf("peer user ip = [%s] port = [%d]n", inet_ntoa(peerAddr.sin_addr), htons(peerAddr.sin_port)); if (sendto(sockServer, (char *)addrUser1, u1Len, 0, (struct sockaddr *)peerAddr, addrLen) == -1) { printf("send to peer user data filed.n"); } if (sendto(sockServer, (char *)peerAddr, addrLen, 0, (struct sockaddr *)addrUser1, u1Len) == -1) { printf("send to connect user data failedn"); } addrList.pop_front(); } else { addrList.push_back(addrUser1); } } }}客户端代码

int main() { int sockClient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); char content[10240] = { 0 }; struct sockaddr_in addrServer = { 0 }; addrServer.sin_family = AF_INET; addrServer.sin_port = htons(10000); addrServer.sin_addr.s_addr = inet_addr("127.0.0.1"); socklen_t nLen1 = sizeof(addrServer); sendto(sockClient, content, 1, 0, (struct sockaddr *)addrServer, nLen1); struct sockaddr_in addrUser = { 0 }; char content2[10240] = { 0 }; if (-1 == recvfrom(sockClient, content2, sizeof(content2), 0, (struct sockaddr *)addrServer, nLen1)) { } else { memcpy(addrUser, content2, sizeof(addrUser)); sprintf(content2, "hello, user ip = [%s] port = [%d]n", inet_ntoa(addrUser.sin_addr), htons(addrUser.sin_port)); if (-1 == sendto(sockClient, content2, strlen(content2), 0, (struct sockaddr *)addrUser, nLen1)) { } else { if (-1 == recvfrom(sockClient, content2, sizeof(content2), 0, (struct sockaddr *)addrServer, nLen1)) { } printf("%s", content2); } } }

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。