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);

所以现在从技术上讲,我正在侦听我用来连接服务器的同一端口,该服务器已登录并且可以检索到另一个客户端,并且我的 ip 和端口位于 NAT 表中。我不确定我错过了什么,或者是否有一些协议或我必须做的事情。我看过 TCP 和 UDP 打孔,但我不确定它是如何实际完成的或如何实现它。

任何建议,将不胜感激。

4

2 回答 2

2

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

鉴于您的架构,这意味着所有客户端都需要让他们的路由器进行端口转发,这当然是不可行的(想象 gtalk 或目标要求用户进行端口转发)。

更常见的架构是让服务器完成向连接的客户端重新广播消息的工作,并维护表以查找谁与谁交谈。这样就有一个服务器需要一个静态 IP(或端口转发),所有用户只是连接到服务器套接字并从中读取消息的客户端。

有关描述第二种架构的实际代码,请参阅http://pirate.shu.edu/~wachsmut/Teaching/CSAS2214/Virtual/Lectures/chat-c​​lient-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.

于 2013-04-10T00:06:09.503 回答
2

交互式连接建立 (ICE) 协议结合了各种 NAT 穿越实用程序,例如 STUN 和 TURN 协议,以提供一种强大的机制,允许基于提供/应答的协议(例如 SIP 和 XMPP)穿越 NAT。

该项目提供了 ICE 协议的 Java 实现,SIP 和 XMPP 应用程序都可以使用它。该项目还提供了套接字共享和对伪 TCP 的支持等功能。

ice4j 由Jitsi社区维护。

冰4j

于 2017-04-19T15:34:04.067 回答