C++ 为什么数据包可以';NAT穿越数据包发送后是否接收不到?

C++ 为什么数据包可以';NAT穿越数据包发送后是否接收不到?,c++,c,linux,tun,C++,C,Linux,Tun,我正在建立一个基于TUN设备的虚拟专用网络程序,其中最重要的部分是NAT遍历。编写完这个程序后,我使用同一局域网中的两个设备进行调试 但我注意到了一件奇怪的事情,假设a想要向B发送数据包,并且有一个外部服务器S具有静态IP。我使用最常用的方法在UDP中实现NAT遍历 A向B发送数据包,B的NAT可能会放弃该数据包。 然后A向S发送一个请求,S向B发送请求,然后B向A发送一个数据包。从理论上讲,B应该接收来自A的数据包 但我遇到的情况是B从未收到A的包裹 我首先检查了我的NAT类型,它是端口受限的

我正在建立一个基于TUN设备的虚拟专用网络程序,其中最重要的部分是NAT遍历。编写完这个程序后,我使用同一局域网中的两个设备进行调试

但我注意到了一件奇怪的事情,假设a想要向B发送数据包,并且有一个外部服务器S具有静态IP。我使用最常用的方法在UDP中实现NAT遍历

A向B发送数据包,B的NAT可能会放弃该数据包。 然后A向S发送一个请求,S向B发送请求,然后B向A发送一个数据包。从理论上讲,B应该接收来自A的数据包

但我遇到的情况是B从未收到A的包裹

我首先检查了我的NAT类型,它是端口受限的Cone NAT,所以应该可以工作

这是网络结构

我认为这很可能是我的代码错误,但我无法理解

完整的代码已打开,下面是代码的一部分

客户:

intmain(){
...
while(true){
nread=读取(tun_fd,buf.buffer,knl buffersize);
...
联合{
ipv4\u地址\u t i;
uint8_t s[4];
}目的地ip;
dest_ip_n.s[0]=基本缓冲区[16];
dest_ip_n.s[1]=基本缓冲区[17];
dest_ip_n.s[2]=基本缓冲区[18];
dest_ip_n.s[3]=基本缓冲区[19];
buf.header.set(packet\u id.add(),packet\u服务器,
数据包类型握手请求数据包否应答,
sizeof(buf.header)+4,本地虚拟ip地址;
标准::交换(基本缓冲区[0],基本缓冲区[16]);
标准::交换(基本缓冲区[1],基本缓冲区[17]);
标准::交换(基本缓冲区[2],基本缓冲区[18]);
标准::交换(基本缓冲区[3],基本缓冲区[19]);
aes_加密(重新解释强制转换(&buf),buf.header.length,
aes_键,dbuf);
发送煎蛋卷(sockfd、dbuf、,
ceil(buf.header.length/(双)kAesBlockSize)*kAesBlockSize,
0、&server\u addr、server\u addr\u len、buf.header);
标准::交换(基本缓冲区[0],基本缓冲区[16]);
标准::交换(基本缓冲区[1],基本缓冲区[17]);
标准::交换(基本缓冲区[2],基本缓冲区[18]);
标准::交换(基本缓冲区[3],基本缓冲区[19]);
auto res=路由器查询(dest_ip_n.i);
...
buf.header.set(packet\u id.add(),packet\u PEERS,
数据包类型握手数据包否应答,
sizeof(OmeletProtoHeader),本地虚拟ip地址;
aes_加密(重新解释强制转换(&buf),buf.header.length,
aes_键,dbuf);
对等地址{}中的sockaddr{u;
...
socklen\u t peer\u addr\u len=sizeof(sockaddr\u in);
发送煎蛋卷(sockfd、dbuf、,
ceil(buf.header.length/(双)kAesBlockSize)*kAesBlockSize,
0,&peer\u addr,peer\u addr\u len,buf.header);
buf.header.set(packet\u id.add(),packet\u PEERS,
数据包类型原始IP数据包无应答,
sizeof(OmeletProtoHeader)+nread,本地虚拟ip地址;
aes_加密(重新解释强制转换(&buf),buf.header.length,
aes_键,dbuf);
发送煎蛋卷(sockfd、dbuf、,
ceil(buf.header.length/(双)kAesBlockSize)*kAesBlockSize,
0,&peer\u addr,peer\u addr\u len,buf.header);
}
...
}
void recv_线程(){
...
案例数据包类型原始IP数据包:{
int nwrite=
写入(tun_fd,arg->first->data,
arg->first->header.length-sizeof(arg->first->header));
}
...
}
服务器:

case数据包类型握手请求:{
联合{
ipv4\u地址\u t i;
uint8_t s[4];
}目的地ip;
memcpy(dest_ip_n.s,arg->first->data,4);
Peer source\u Peer=al.query(arg->first->header.virtual\u ip\n);
Peer dest_Peer=al.query(dest_ip_n.i);
如果(dest_peer.ip_n==0 | | dest_peer.port_n==0)中断;
arg->first->header.set(packet\u id.add(),packet\u SERVER,
数据包类型握手请求数据包否应答,
sizeof(arg->first->header)+sizeof(Peer),arg->first->header.virtual\u ip\n);
对等地址{}中的sockaddr{u;
...
memcpy(arg->first->data和source\u peer、source\u peer的大小);
aes_加密(重新解释强制转换(arg->first),
arg->first->header.length,aes_键,发送);
煎蛋卷(
sockfd,发送,
(size_t)cell(arg->first->header.length/(double)kAesBlockSize)*
kAesBlockSize,
0,&(对等地址),对等地址的大小,arg->first->header,false);
...
打破
}

我在机器A到B上使用了ping,但没有响应。数据包已成功发送到B,但B无法接收任何数据包。

这似乎是ISP的责任:-似乎是ISP的责任:-#