BitTorrent和Gnutella在传输文件时使用什么来绕过NAT?

2022-09-02 22:28:55

我正在尝试在Java中做一个p2p文件共享原型/软件。我有兴趣学习使用套接字,所以,不,我不会使用JXTA或任何类型的API。

我读过关于TCP打孔的文章,它可能不适用于所有NAT类型。但我可以看到Gnutella和BitTorrent总是在我尝试的每台机器/ NAT上工作。那么他们是否使用 TCP 打孔来启动主机之间的连接呢?

另外,像这样的代码会做TCP打孔吗?

    final ServerSocket s = new ServerSocket(7777);
    Thread t = new Thread(new Runnable(){

        public void run() {
            try
            {
                s.accept();
            }
            catch(Exception ex)
            {

            }
        }
    });

    Socket sock = new Socket();
    sock.connect(new InetSocketAddress("IP ADDRESS", 7777), 50000);

答案 1

我认为通用即插即用(UPnP)是一种协议,使您能够以编程方式在路由器中设置端口转发。不过,我不确定这是否是这些程序使用的唯一方法。

看看 UPnP PortMapper 项目,了解 Java 实现。

这篇 CodeProject 文章看起来也不错,尽管它不是 Java:使用 UPnP 进行编程端口转发和 NAT 遍历


答案 2

您应该首先在维基百科上阅读NAT遍历

然而,实际上,主要使用的方式是UPnP,STUN,TURN,以及ICE,它是STUN和TURN的组合。

由于TCP是一种面向连接的协议,NAT可以控制每个连接的协议,并在连接结束时丢弃所有数据包。
但 UDP 是无连接的,响应可能来自不同的端口或不同的地址(与原始目标相比)。此外,UDP 消息没有确切的超时。因此,NAT 上通常存在较少的 UDP 限制。
因此,许多这些P2P实现都使用UDP或某些基于UDP的协议,如microTP,RUDP,UDT,甚至基于UDP的SCTP(WebRTC基于它)。

您还可以从有关 NAT 遍历、RFC 和 BEP(BitTorrent 文档)的文章中学习。

编辑:甚至还有一种更有趣的方式 - ICMP遍历。事实上,ICMP(特别是TTL排除消息)在NAT上的限制甚至比UDP还要小,因为错误消息可以从互联网的每个角落发送,并且具有NAT的路由器无法意识到这些消息不是真实的消息。但是,发送 ICMP 数据包需要类 Unix 系统上的 root 权限,以及 Windows 上的管理员权限。


推荐