ServerSocket 正在使用 ip /::

ServerSocket is using ip /::

我正在为 android 制作一个聊天应用程序,目前正在使用 2 个模拟器和一个通过 USB 连接的 phone 进行测试。 在过去的 24 小时里,我几乎无法让 Socket 连接到 ServerSocket。每个主机都使用 ServerSocket 以通过其客户端套接字侦听其他主机 "talk"。

对于两个模拟器,打印出以下两行代码: The server socket is using ip: /::

serverSocket = new ServerSocket(portNo);
Log.i("MY_TAG", "The server socket is using ip: " + serverSocket.getInetAddress() );

使用下面的代码行,我得到一个 ConnectionException 说它无法连接到指定的 ip 和端口并且连接超时:

socket = new Socket(addr, portNo);

我获取 ip 的方式是大约每 20 秒查询一次服务器,在 php 脚本中,我使用 $_SERVER['REMOTE_ADDR'] 这确实返回了我的 ip 地址。

当使用 phone 向模拟器发送消息时,我收到一个略有不同的错误。我得到一个 ConnectionException 就像模拟器一样,除了它还说 "Connection refused".

当从模拟器向 phone 发送消息时,由于超时,我得到一个 ConnectionException。

phone 的 ServerSocket 使用 ip 0.0.0.0,我知道这很好,因为这意味着它只是在所有接口上监听。

在所有情况下,Server Socket 的 accept() 方法从不 returns。

使用 netstat -an(我使用 Windows 作为我的 OS),我没有在输出中看到我的 ServerSockets 应该监听的任何端口。

使用 telnet,我在模拟器上尝试时收到连接被拒绝的消息(使用 php 的 $_SERVER['REMOTE_ADDR'] 获取 ip)。
在 phone 的 ip 和侦听端口上使用 telnet 时出现连接超时。

也就是说,请帮我弄清楚如何连接这些套接字。

简单的答案是我试图做的事情是不可能的(至少在不跳过一些障碍的情况下是不可能的)。问题是两台主机都在 NAT 路由器后面。 NAT 路由器的工作方式是当传入消息到达它们时,它们会查看消息中的端口号,然后将其转换为内部 ip 和端口号,对应于隐藏在它后面的本地网络中的某个主机。这是使用称为 NAT 转换 table 的东西完成的。我的设计的问题是,对于从世界到 NAT 的传入消息,我向 NAT 提供了内部端口号,而实际上我应该向 NAT 提供消息发送时 NAT 分配给主机内部端口的任何端口号. 这是一张描述我所说内容的图片(摘自加州大学圣地亚哥分校杰出的网络教授 Alex C. Snoeren 的讲座幻灯片):

我的解决方案是重新设计我正在做的事情,让一个 ServerSocket 始终侦听某些网络主机上的新连接。