1

我想用 Java 创建一个简单的聊天程序,它可以在 p2p 基础上工作。使用公共服务器仅启动连接。但我什至不确定这是否可能。

如果至少有一台 PC 转发了正确的端口,我成功地用 Java 实现了聊天解决方案。我还设法使用外部服务器,而不是必须在客户端转发端口。

所以我什至有可能以某种方式使用公共服务器来启动连接,而不是在客户端之间发送数据,从而减轻服务器的负载?

我不太熟悉路由器的工作原理,但我希望当您从内部 IP 调用公共服务器时,路由器会记住来自该公共 IP 的呼叫和传入响应,而不是发送到您的 PC。所以我想,也许如果第一个客户端连接到服务器,服务器比将信息传递给第二个客户端,也许他们可以以某种方式直接通信?如果路由器中的规则是由服务器建立的?

我希望我解释清楚。如果没有,请原谅我。我什至不知道这到底是怎么做到的,我只是想知道我的概念是否正确,我必须更加努力地学习,以便有机会实现它。谢谢。

4

3 回答 3

5

我认为TeleHash是一个新项目,可以做这样的事情。我最近才发现它,所以我不太了解它。

我制作了这个答案社区 wiki,以便其他人可以对其进行更新以解释 TeleHash 如何用于此目的。

于 2011-04-16T18:12:17.617 回答
4

这是一个广泛的主题,搜索打孔(对于 TCP:http ://en.wikipedia.org/wiki/TCP_hole_punching )

于 2011-04-16T17:59:28.130 回答
-2

编辑:在评论(并阅读链接页面)之后,我应该撤回我的建议。为了漂亮的图形,我没有删除它,但更改了最后一部分。


如果我理解正确,您在 NAT 防火墙后面都有两个客户端,它允许传出连接,但如果没有特别配置为这样做,则不会转发传入连接(因为他们不知道它的目的地是哪个本地主机)。

原则上,一个 TCP 连接在其整个存在期间总是连接相同的两个 IP 地址和这些地址的端口号(例如,我们有四个保持不变的数字)。在 NAT 情况下,您实际上有两个连接,但这在客户端计算机 A(也从服务器 S)中不可见:

Client A  -------(LAN)------ NAT B      ------ (Internet) -------- Server S
  IP A                   IP B1 | IP B2                               IP S
  Port a                       | Port b                              Port s

TCP 数据包在 LAN 部分具有 [A:a / S:s](或 [S:s / A:a])地址和 [B2:b / S:s](或 [S:s / B2:b ]) 互联网部分的地址。连接由这个 [IP:port / IP:port] 四元组标识,因此如果您尝试更改四个数字中的一个,这必须是一个新连接(否则数据包将被丢弃)。

因此,如果您首先与您的服务器通话,您将无法继续与同一连接上的其他客户端通话,除非服务器正在转发内容。

UDP 数据包实际上也是如此,不同之处在于没有连接,并且 NAT 必须聪明并猜测哪个数据包是另一个数据包的答案,并因此将其转发到正确的方向。

正如评论和其他答案所指出的,这就是 NAT 可以被欺骗的地方:我们首先向另一个客户端发送一个 UDP 数据包,该数据包将被那里的 NAT 丢弃。但是随后另一个客户端发送了一个应答包,该应答包不是对传出包的真正应答(因为由于其他客户端的 NAT,这个包从未收到过),但 IP 地址和端口号匹配,它仍然会被允许通过。如果 NAT 也转换端口号,这可能会变得更加复杂。

对于 TCP,它可以类似地工作,如果两个 NAT 都没有真正保持打开的连接,而是在之前发送 SYN 时简单地转发(更改)数据包。它甚至更复杂,因为这里的 TCP 序列号也必须匹配。

于 2011-04-16T17:58:27.227 回答