【问题标题】:Help communicating with sockets through nat帮助通过nat与socket通信
【发布时间】:2010-12-16 17:01:25
【问题描述】:

我想在 java 中制作一个简单的 p2p 信使,我已经设法与同一网络中的两台计算机进行通信,但是当我尝试从网络外部向另一台计算机发送消息时,消息正在消失......我知道我可以在路由器中进行转发,但我不想这样做,我想让它像 yahoo、gtalk 或其他 im 服务器一样。 我认为他们使用 nat 系统来做到这一点,但我不太清楚如何:D。

有人可以解释一下 NAT 的工作原理吗?如果这是解决我的问题的方法吗?

我读到我需要服务器的静态和公共 ip,当客户端(具有私有 ip)向服务器发送请求时,他的 NAT 将知道如何处理接下来来自服务器的消息时间......但是如果客户端不向服务器发送数据包并且服务器向客户端发送数据包,那么 NAT 不知道将数据包发送到网络内的哪里(到客户端)。

我的想法对吗?

非常感谢!

【问题讨论】:

    标签: java sockets network-programming


    【解决方案1】:

    您的 NAT 描述几乎是正确的。您犯的唯一错误是 Peter 指出的 - 客户端始终是发起连接的那个。

    现在,如果双方都有公共 IP,一切都很好,任何一方都可以是服务器。

    如果一侧在 NAT 后面,而另一侧有公共 IP,那么如果 NAT 后面的那一侧发起连接就可以了。在这种情况下,NATing 路由器会记住从服务器发送响应的位置。

    最后,如果双方都在 NATs 之后,看起来不可能发起连接,但实际上并非总是如此。有一个技巧叫做“hole punching”。这是一种白魔法,它并不总是有效,但它经常有效,足以被 Skype 成功使用。

    【讨论】:

    • 另外,有些路由器允许通过UPNP定义动态端口转发,但必须启用。如果双方都在 NAT 之后,那将是我推荐的方式。
    • 谢谢你的回答,现在我明白了!
    • 也就是说,如果您可以访问这些路由器。如果路由器属于您的 ISP,那可以吗?
    • 我也有同样的问题。我是套接字编程的新手。我在 android 中做聊天应用程序。它在内部网络中工作,但是当涉及到不同的网络时,它会失败。你能给我推荐一些可以阅读的资源或任何好的例子吗?
    【解决方案2】:

    根据定义,客户端发起请求,服务器为请求提供服务并返回响应。假设是可以信任客户端进行网络连接,而服务器则不能。顺便说一句:在某些网络上,客户端甚至不被信任这样做,必须使用代理。

    我再说一遍;客户端是创建连接的人,无论是在您的网络上还是在互联网上。

    【讨论】:

      【解决方案3】:

      您提到的所有其他系统都使用具有众所周知的公共 IP 的服务器来帮助客户端相互通信。每个客户端都与服务器通信,服务器将每条消息发送到相应的客户端。这可能是唯一的方法,否则:

      • 每个客户端都应该有一个公共 IP,以便其他客户端可以联系到他。每个客户端还应同时充当客户端和服务器。
      • 很难发现客户,因为您需要知道他们的 IP

      您的系统可以在本地网络中运行,但不能在互联网中运行。网络中的每台计算机都有一个由本地网关分配给它的本地 IP。这个本地 IP 对外人是不可见的,除非有 NAT 设置将公共 IP 映射到它。还必须有一个传出消息的设置。

      【讨论】:

      • 并非每个 ISP 都提供本地 IP 地址。我有两个 Internet 连接,其中一个通过 PPP 给我一个公共 IP,而且几乎总是相同的。即使它有时会发生变化,我也设置了 DynDNS。另一个连接使用固定的私有 IP,但后来我要求他们将 IP 切换为公共 IP。现在我有一个固定的公共 IP,但我必须为此付费(虽然很少)。
      • 当然,但是如果您创建家庭网络,第二台计算机将获得本地 IP。事实上,如果您使用的是路由器,很可能甚至您的第一台计算机都有本地 IP,而对您的公共 IP 一无所知。