Java NAT穿透聊天应用程序

6
我正在尝试为我的网络课程创建一个Java聊天应用程序。目前,我卡在试图连接到另一个路由器后面的人身上。我现在的项目是有一个客户端程序和一个服务器程序。客户端程序首先登录到服务器程序,将他们的IP和端口记录在数据库中,然后服务器将他们的朋友列表以及其IP和端口发送回给他们。然后,客户端关闭与服务器的连接,并尝试使用服务器返回的信息连接到另一个客户端。到目前为止,我的程序只能连接到服务器并获取朋友的IP和端口,但是当我使用这些值连接到其他客户端时,无法连接。
socket = new Socket();
socket.setReuseAddress(true);
socket.setKeepAlive(true);
socket.setSoLinger(true, 10);
socket.bind(new InetSocketAddress(Port));
socket.connect(new InetSocketAddress(host, SERVER_PORT));
reusePort = socket.getLocalPort(); 

以下是用于连接服务器的Java代码片段,然后以下是我在客户端上执行的操作。
ss = new ServerSocket(reusePort);

现在,技术上说,我正在监听与连接服务器使用的相同端口,该端口已登录并可从另一个客户端检索,在NAT表中具有我的IP和端口。 我不确定我缺少什么或是否需要执行某些协议或其他操作。 我已经查看了TCP和UDP协议穿透,但我不确定如何实际完成或如何实施它。

如果有任何建议,将不胜感激。


1
我看到你已经接受了一个答案,但是似乎你想了解“打洞技术”。被接受的答案并没有真正回答你的问题,而是告诉你让应用程序的所有信息都通过服务器传输,而你似乎想直接连接客户端。 - Mattias F
嘿,你找到答案了吗?请帮帮我,我也遇到了同样的问题。 - Sagar Nayak
2个回答

2
如果您想发送消息,需要在任何充当服务器(创建套接字服务器的任何设备)的设备上设置端口转发。端口转发是在路由器上完成的。您无法连接到其他客户端的原因是它们隐藏在其路由器防火墙后面。他们对世界的地址实际上是路由器的地址,而不是他们物理计算机的地址。在他们的本地网络中,他们有一个与世界其他地方看到的不同的地址,路由器根据地址转换表确定来自外部世界的消息需要发送到客户端。

鉴于您的架构,这意味着所有客户端都需要进行端口转发,这当然是不可行的(想象一下gtalk或aim要求用户进行端口转发)。

更常见的架构是让服务器负责重新广播消息到已连接的客户端并维护表以查找谁在与谁交谈。这样,只需要一个服务器需要静态IP(或进行端口转发),所有用户都是简单地连接到服务器套接字并从中读取消息的客户端。

有关描述第二种架构的实际代码,请参见http://pirate.shu.edu/~wachsmut/Teaching/CSAS2214/Virtual/Lectures/chat-client-server.html。然后运行服务器代码的机器需要静态IP,或者如果它在路由器后面,则需要将监听端口的流量转发到其地址。

因此,在服务器代码上,您将绑定到从路由器分配的IP(例如192.168.1.2)和某个端口(比如5000)。然后转到路由器的配置页面(可能是192.168.1.1,请参见http://www.wikihow.com/Port-Forward/Open-Ports-on-a-Linksys-Router),并将端口5000转发到地址192.168.1.2。


谢谢tigger!我现在已经将我的服务器端口转发到路由器后面的X,我正在考虑切换到你建议的第二种架构(感谢链接,有时候在谷歌上筛选很困难),让每个客户端维护与服务器的单个连接,然后服务器通过它向他们转发任何内容。不过,我会再尝试一下我现在的设置,然后在时间允许的情况下再进行切换。感谢您的帮助。 - DarkLazar
好的,你是说由于我们无法访问每个路由器,所以我们要通过端口转发来实现。因此,我们应该使用服务器来完成这项工作(如果我理解有误,请纠正我)。那么服务器具体会做什么呢?请原谅我的问题可能有些奇怪,我对网络不太了解。 - Sagar Nayak
@DarkLazar 这就是种子客户端的工作方式吗?还是它们使用其他方法来实现这一点?有没有更简单的实现方式(比如库)? - goodbytes

2
ICE协议是一种交互式连接建立协议,它结合了STUN和TURN等多种NAT穿透工具,提供了强大的机制,使得基于Offer/Answer的协议(如SIP和XMPP)能够穿越NAT。本项目提供了ICE协议的Java实现,可供SIP和XMPP应用程序使用。该项目还提供了套接字共享和Pseudo TCP支持等功能。ice4j由Jitsi社区维护。ice4j

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接