XMPP 可以在 NAT 环境中工作吗?
XMMP 服务器使用 NAT 向客户端提供的公共端点(IP + 端口)向 NAT 后面的客户端发送推送通知。但是这个端点被 NAT 分配给这个特定的客户端多久,如果 NAT 将相同的端点分配给另一个客户端会发生什么?这个问题如何解决?
An XMMP server sends push notifications to a client behind a NAT using a public endpoint( IP + Port) supplied by NAT to client. But how long this endpoint is assigned to this specific client by NAT, what will happen if NAT assigns same endpoint to another client ? How this problem can be solved?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
XMPP 使用标准 TCP 连接。只要连接处于活动状态,NAT 就会保持关联(除非它们严重损坏)。
更新:我的发言的最后部分本来可以扩展一下。严重损坏的 NAT 实现确实存在。一般来说,这些比例很小,但许多(大多数?)流行的 XMPP 客户端确实确保它们通过空闲连接发送某种保持活动的消息。
您可以使用三种保活,我将按照带宽/处理要求的顺序在此处列出它们:
TCP保活是一个很好的轻量级选项,特别是一旦启用它们,它们就会由操作系统自动处理。如何启用它们取决于您的语言和框架,但在最低级别,您需要在套接字上启用
SO_KEEPALIVE
选项。TCP keepalive 有两个问题。一是您无法从应用程序控制它们(除非您编写特定于平台的代码)。第二个问题是一些 NAT 实现如此被破坏以至于它们也会忽略 TCP keepalive!但现在你的比例有望下降到很小。
因此,另一个选择是空白保活。由于这些涉及跨流的数据,因此即使是忽略 keepalive 的损坏的 NAT,您也应该是安全的。
空白保活仅涉及在任何空闲时通过 XMPP 流发送空格字符 (' ')。 XML 和 XMPP 允许元素之间有无限的空白,并且它会被接收者忽略。
最后,您可以使用成熟的 XMPP ping (XEP-0199)。这些涉及结束到服务器的实际
'get' 节,然后服务器必须进行回复。这可以确保数据在两个方向上流动,并且即使是最糟糕的 NAT 实施也应该使您的连接保持活动状态。好吧,我应该提到还有一类更糟糕的 NAT。我见过 NAT 会因为多种原因而简单地“忘记”您的映射,包括它们的映射表已满,或者刚好在计时器之后。您无法解决这些问题,它们不适用于任何长期 TCP 连接。此时您可能能做的最好的事情就是使用 BOSH (本质上是 XMPP HTTP)。
结论:如果您担心您的应用程序可能在其中某些设备后面运行,我建议使用类似以下算法的算法(确切时间可能会调整,但我建议将它们作为最小值):
由于损坏的 NAT 设备的行为超出了任何标准协议规范,因此自然不可能设计出始终适用于所有这些设备的完美解决方案。您只需要接受这些只是一小部分,并且这些对于工作 NAT 设备来说都不重要(尽管还有其他类型的网络中断可能使定期保持活动/ping 成为一个好主意,具体取决于您的应用程序的需求)。
XMPP uses a standard TCP connection. NATs will keep the association for as long as the connection is alive (unless they are horribly broken).
Update: The last part of my statement could have been expanded a bit. Horribly broken NAT implementations do exist. Generally these are a small percentage, but many (most?) popular XMPP clients do ensure they send some kind of keepalive over idle connections.
There are three kinds of keepalive you can use I'll list them here in order of bandwidth/processing requirements:
TCP keepalives are a good lightweight option, especially as once they are enabled, they are automatically handled by the OS. How to enable them will depend on your language and framework, but at the lowest level, you need to enable the
SO_KEEPALIVE
option on the socket.There are two problems with TCP keepalives. One is that you can't control them from your application (unless you write platform-specific code). The second problem is that some NAT implementations are so broken that they will ignore TCP keepalives too! But you're hopefully down to a very small percentage now.
So another option is whitespace keepalives. Since these involve data going across the stream, you should be safe from even the broken NATs that ignore keepalives.
Whitespace keepalives simply involve sending the space character (' ') across the XMPP stream at any time it is idle. XML and XMPP allow unlimited whitespace between elements, and it is simply ignored by the recipient.
Finally, you can use fully-fledged XMPP pings (XEP-0199). These involve ending an actual
<iq/>
'get' stanza to the server, which then must reply. This ensures data flows in both directions, and should make even the most broken NAT implementations keep your connection alive.Ok, I should mention that there is an even worse class of NAT. I have seen NATs that will simply 'forget' about your mapping for a range of reasons, including their mapping table being full, or just after a timer. There is nothing you can do to work around these, they don't work with any long-lived TCP connections. The best you could probably do at that point is use BOSH (essentially XMPP over HTTP).
Conclusion: If you are concerned that your application may run behind some of these devices, I suggest something like the following algorithm (exact times may be tweaked, but I recommend these as minimum values):
Because the behaviour of broken NAT devices is beyond any standard protocol specification, it is naturally impossible to devise a perfect solution that will work with all of them, all of the time. You just have to accept that these are a small minority, and none of this matters for working NAT devices (though there are other kinds of network breakages that may make regular keepalives/pings a good idea, depending on the needs of your application).
解决方案是发送保活消息来维护 NAT 条目。通常使用 XMPP 空白。例如每十分钟发送一次,以保持指定客户端的可达性。
您必须记住,NAT 不是标准化技术。因此有不同的实现方式。上面评论中提供的 RFC 来自 BEHAVE 工作组。
The Solution is sending keep alive messages to maintain the NAT entry. XMPP whitespace is typically used. Send it eg every Ten minutes to preserve reachability of the nated client.
You have to keep in mind that NAT is no standardized technique. Thus there are different implementations. The provided RFCs in the comment above is from the BEHAVE working group.