如何在创建与外部主机的连接时获取NAT的外部端口以及如何在Java中实现STUN

时间:2011-11-13 09:20:10

标签: java protocols traversal nat stun

我正在研究NAT和STUN协议,但我还没有理解它们,所以我尝试用Java实现STUN。

假设我有2台计算机通过2个相应的全锥NAT设备连接到Internet,我正在尝试用Java实现STUN协议,我只是在2个对等端都知道外部IP和端口时实现该部分彼此之间,其中一个(让我们称这个对等体为“客户端”)试图向另一个发送消息(这个对等体是“服务器”)。我做了类似的事情:

  • 在服务器上,我打开了一个套接字:

    ServerSocket sv = new ServerSocket(0);
    

    然后我通过这个网站http://www.whatismyip.com获取服务器的IP,并获得由以下网址打开的端口:

    System.out.println(sv.getLocalPort());
    
  • 在客户端,我通过以下方式向服务器发送消息:

    Socket sk = new Socket(serverIP, serverPort);
    PrintWriter pw = new PrintWriter(sk.getOutputStream(), true);
    pw.print("Hello there");
    pw.close();
    sk.close();
    

但是服务器无法接收任何内容,所以我有一些问题:

  1. 我认为我通过上面的方式获得的服务器外部端口不是另一个对等体用来向服务器发送消息的外部端口,那么用Java获取它的正确方法是什么?

  2. 我做的方法是在与STUN服务器交换后,当2个对等方知道对方的外部ip和端口时,实现STUN部分的正确方法?如果不是,那么正确的方法是什么?

  3. 希望大家为我解释一下,谢谢大家!

2 个答案:

答案 0 :(得分:0)

大多数NAT系统都不会为私有地址空间中的侦听套接字打开隧道。您必须要求管理员为您打开端口并将端口传送给远程对等端,或者您必须使用uPNP's Internet Gateway Device Protocol(实际上并非标准化,但许多路由器实现它)来请求NAT打开特定的端口。

从我可以阅读的STUN RFC开始,它出现 ,以假设用于与STUN协调服务器通信的端口将是客户端可能使用的端口连接到第一个STUN对等体。对于RFC而言,这似乎是一个令人惊讶的假设,因为它给NAT路由器带来了令人难以置信的负担,无法将相同的端口重复地发送到同一个客户端,从而使NAT数据包传送规则大大复杂化。我希望我在这里错了。

答案 1 :(得分:0)

您需要一个知名的STUN服务器,它位于公共互联网的某个位置,充当协调员。这样的STUN服务器可以帮助两个对等体发现彼此的公共地址和端口。您拥有全锥形NAT的事实只有在同伴相互了解并开始通信之后才有帮助。如果它不是全锥形,则STUN服务器可能需要在对等体之间中继所有流量!

最相关的规范是:

至于Java实现,我发现littleshoot stun stack处于非常好的状态。