关于TCP打洞和UDP打洞

为什么网上讲到的P2P打洞基本上都是基于UDP协议的打洞?难道TCP不可能打洞?还是TCP打洞难于实现?假设现在有内网客户端A和内网客户端B,有公网服务端S。如果A和B想要进行UDP通信,则必须穿透双方的NAT路由。假设为NAT-A和NAT-B。

A 发送数据包到公网S,B发送数据包到公网S,则S分别得到了A和B的公网IP,S也和A B 分别建立了会话,由S发到NAT-A的数据包会被NAT-A直接转发给A,由S发到NAT-B的数据包会被NAT-B直接转发给B,除了S发出的数据包之 外的则会被丢弃。所以:现在A B 都能分别和S进行全双工通讯了,但是A B之间还不能直接通讯。

 

解决办法是:A向B的公网IP发送一个数据包,则NAT-A能接收来自NAT-B的数据包并转发给A了(即B现在能访问A了);再由S命令B向A的公网IP发送一个数据包,则NAT-B能接收来自NAT-A的数据包并转发给B了(即A现在能访问B了)。以上就是“打洞”的原理。但是TCP和UDP在打洞上却有点不同。这是因为伯克利socket(标准socket规范)的API造成的。UDP的socket允许多个socket绑定到同一个本地端口,而TCP的socket则不允许。

 

这 是这样一个意思:A B要连接到S,肯定首先A B双方都会在本地创建一个socket,去连接S上的socket。创建一个socket必然会绑定一个本地端口(就算应用程序里面没写端口,实际上也是 绑定了的,至少java确实如此),假设为8888,这样A和B才分别建立了到S的通信信道。接下来就需要打洞了,打洞则需要A和B分别发送数据包到对方 的公网IP。但是问题就在这里:因为NAT设备是根据端口号来确定session,如果是UDP的socket,A B可以分别再创建socket,然后将socket绑定到8888,这样打洞就成功了。但是如果TCPsocket,则不能再创建socket并绑定到 8888了,这样打洞就无法成功。

 

posted @   大空白纸  阅读(1646)  评论(0编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示