UDP打洞

提到UDP打洞,先提一个概念叫做NAT。NAT就是把局域网内多个ip地址映射到公网上,从而能完成局域网到公网的访问。但是NAT有一个特性,就是必须先从局域网到公网上建立映射,而后公网才能和局域网之间进行相互通信。如果两个局域网之间的机器要借助公网进行通信,这时就需要打洞了。UDP打洞要借助一个打洞服务器,打洞服务器在公网上。

核心思路:
1.机器A,B,C等众多需要打洞的服务向打洞服务器注册。
2.A向打洞服务器发起向B打洞的请求。
3.B接收到向A的打洞请求,发送任意数据。(此时会被丢弃)
4.A在向B发起打洞请求,即发送任意数据。(此时打洞成功)
注意:3.4步骤顺序可颠倒,但是第一个请求肯定都会被丢弃。
server端

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>

#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#include <Iphlpapi.h>
#pragma comment (lib, "Ws2_32.lib")
#pragma comment(lib,"Iphlpapi.lib")
int ioctl(int fd, long cmd, u_long *ptr) {
	return ioctlsocket(fd, cmd, ptr);
}
int close(int fd) {
	return closesocket(fd);
}
#else
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <error.h>
#endif // !_WIN32

//中间枢纽获得A客户端的外网ip和port发送给客户端B,获得客户端B的外网ip和port发送给A
//B通过A打的洞发数据给A,这时候A拒收B的消息,因为A的nat映射中没有B的信息,但是这次通
//信却在B的网管中添加了映射可以接受A的
//消息,同理A通过B打的洞发数据给B,这时候由于B可以接受A的消息,所以数据接收成功且在A
//的映射中加入了B的信息,从而A与B可以跨服务器通信。实现p2p
/* 由于已知的外网服务器S可能并没有AB客户端的映射关系,所以要先建立A与S 还有 B与S之间的映射,这样才能进行udp穿透。 */

#define ERR_EXIT(m)\
    do{\
        perror(m);\
        exit(1);\
    }while(0)

/* 用来记录客户端发送过来的外网ip+port */
typedef struct {
	struct in_addr ip;
	int port;
}clientInfo;

int main()
{
	/* 一个客户端信息结构体数组,分别存放两个客户端的外网ip+port */
	clientInfo info[2];
	/* 作为心跳包需要接收的一个字节 */
	/* char ch; */
	char str[10] = { 0 };

#ifdef _WIN32
	WORD wVersionRequested = MAKEWORD(2, 2);
	WSADATA wsaData;
	WSAStartup(wVersionRequested, &wsaData);
#endif //_WIN32

	/* udp socket描述符 */
	int sockfd = ::socket(AF_INET, SOCK_DGRAM, 0);
	if (sockfd == -1)
		ERR_EXIT("SOCKET");

	struct sockaddr_in serveraddr;
	memset(&s
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值