我正在尝试建立一个P2P即时消息系统,虽然我还没有遇到这个问题,但如果客户端在本地局域网上支持NAT,我预计会遇到一些问题(阅读:所有人。)< / p>
让我解释算法,你会明白我的意思。有三个组件:服务器和两个客户端 - 客户端Alice想要与客户端Bob进行聊天。服务器只跟踪谁在线,但实际的会话不通过服务器(为了客户的隐私)
因此,Alice和Bob都登录到服务器 - 从短暂端口连接到服务器的静态侦听端口。他们告诉服务器他们正在监听传入聊天请求的静态端口。 Alice问服务器她如何联系Bob。服务器响应ipaddress和侦听端口等。 Alice在该IP地址和端口上向Bob发送请求以建立连接。希望这是有道理的。
如果Bob支持NAT,那么确定他可以与服务器通话,因为他是开始通信的人。但Alice的请求不会告诉他,因为他正在收听来自Alice的IP地址的聊天请求的端口尚未建立NAT关系。
是否有某种黑魔法有人知道要做这项工作?这不是一个问题吗?发展并不是那么遥远,我还没有真正解决这个问题。
说明显而易见,我不想让最终用户为他们的侦听端口配置端口转发。
对于前面提到的黑魔法,客户端和服务器都在java中,但我通常只是在算法之后(如果可能的话)
答案 0 :(得分:1)
检查ICE。
大多数P2P框架,如Java中的JXTA,都使用 relay 服务器的原理。
说A想要连接到B,B就在防火墙后面。
- both A and B establish ** outbound ** synchronous (or full duplex/websockets) connections to Relay Server R
- A signals to R that it wants to transmit data to B
- R 'binds' the inbound connection from A to the outbound connection to B (the synchronous HTTP response to B for instance)
- A sends data to R which is relayed to B
关键是所有连接都已建立出站(通常使用友好防火墙协议,如众所周知的端口上的HTTP)
当你有分布式继电器时,事情显然会更加复杂;然后,您需要通过依赖分布式哈希映射(DHT)维护信息的中继来维护到各个对等体的路由的“路由器”。
答案 1 :(得分:0)
没有黑魔法。如果两个客户端都在NAT后面,则消息必须通过第三方(服务器)。 如果只是关于短信的话,我会考虑将这种架构用于所有通信(如果隐私是一个问题,你可以想到某种加密)。服务器(或多个服务器)将更加加载,但您可以更简单(在某些情况下更可靠)架构。例如,如果Alice向Bob发送消息,并且Bob有一些网络问题,则服务器可以排队并保留消息一段时间并稍后交付(即使Alice离线)。另一件事是会议(小组)聊天。仅使用P2P处理它更具挑战性(但可能非常有趣)。但如果所有客户都在NAT后面,你会遇到同样的问题。 我还强烈建议为所有发送和接收的消息(来自客户端和服务器)实现应用程序级确认机制。 TCP / IP等协议不够可靠。