为实时数据/移动设备设计网络协议

时间:2010-01-17 08:29:39

标签: java tcp network-protocols

我面临以下两难困境:

设计一种新的网络协议,用于服务器(Java软件)与桌面和移动客户端之间。移动客户端包括J2ME,Android以及未来甚至iPhone。

数据流是一个实时,恒定的流,也有更多不常见的部分。客户端显示此数据的波形以及不需要立即更新的数据。客户端也应该通过身份验证。

如果可能的话,我想避免从头开始创建完全自定义的TCP协议实现。

现在人们通常建议用REST风格做所有事情,我也非常喜欢。在这种情况下,我有点犹豫不决:如何在REST之上实现恒定的数据流?一个分块的HTTP响应?

我也在考虑非明文协议(我正在替换的当前协议是二进制协议)。那些当前的协议有其相当严重的问题,所以它们确实应该被替换。

Google协议缓冲区看起来非常适合处理低级细节,但我不确定它是否可以在Android上使用。而且我很确定iPhone实现也会遇到问题。

还有BEEP,但我认为它已经死了,我想它是否被广泛使用。

有什么想法吗?

4 个答案:

答案 0 :(得分:8)

我认为在进入协议设计之前,您应该非常仔细地处理以下问题:

  • 目前几乎所有除HTTP之外的协议都会被防火墙过滤。甚至很多内容类型和端口(80除外)都可能被服务提供商过滤,特别是在移动数据服务中。因此,在选择使用或设计协议之前,请确保目标网络中没有防火墙问题。
  • 大小和速度很重要。尝试在传输邮件大小和编码/解码(序列化/反序列化)速度中使用高效协议。 Google Protocol Buffers为此问题提供了可靠的解决方案。
  • 连接始终断开连接。由于NAT超时(默认为15分钟),协议超时(TCP为30分钟)以及许多现有网络问题,您永远不能依赖连接长时间保持打开状态。因此,不要仅仅因为它保持连接打开而不喜欢另一个协议(它可能会尝试,但永远不会成功)。发送心跳对于超时问题是一个很好的尝试,但网络断开仍然是不可避免的。
  • 吞吐量很重要。通过吞吐量,我的意思是在一段时间内(例如1秒)处理的消息数量。使用在接收到消息后断开客户端的异步协议,确实有助于提高吞吐量。虽然不依赖于从服务器连接到客户端来推送结果,因为许多客户端都在NAT和防火墙后面,这避免了从外部直接连接。尝试保持连接打开或轮询服务器以获得结果。在会话中避免状态也是另一种有助于随着客户端数量的增长而扩展应用程序吞吐量的方法。
  • 现有广域网中没有实时。不要相信那些表示已实施基于现有广域网协议的实时协议的人。您永远不能在非实时协议之上实现实时协议。你可以尽力而为网络祈祷。这意味着:不要停下来,尽力而为。
  • 非阻止IO。 NIO(非阻塞IO)现在已成为趋势,有效地用于网络编程。它支持大量连接,内存使用量更少,线程数量有限。 Java 5对NIO有本机支持,非常原始。许多框架,例如Apache MINANetty,都是基于Java NIO实现的,可以使非阻塞编程更容易,更健壮。我强烈推荐他们。

答案 1 :(得分:3)

您可以查看Kryo和/或KryoNet,它们是基于NIO和Java的,可以使用桌面和Android。你必须编写iPhone方面,这将是相当棘手的。 Kryo以序列化大小(benchmarks here)击败谷歌的协议缓冲区并且易于使用(不需要编写.proto类型模式,Kryo的Java类定义是模式)。

关于NIO,您可以查看NPTL。旧的再次成为新的。

答案 2 :(得分:2)

您可能希望查看RTP (Real-time Transport Protocol),这可能不是直接有用(和/或可能过度杀伤),但它的设计会为您提供一些好的想法。你很可能会使用它。

答案 3 :(得分:2)

这不是一个优雅的解决方案,但是您可以通过直接http执行此操作,方法是不在http响应上设置content-length字段,并且永远不会关闭输出流。只需继续发送数据。

您还可以设置非常大的内容长度并实时从服务器发回数据,直到服务器发送了该数量,然后客户端可以选择是否发出新请求。

不幸的是,我找不到任何有用的链接来表达这些想法,但我相信你能得到这些想法。

这些想法的真正好处在于它们超过了http,它可以解决防火墙问题,并且可以将您的应用程序实现为带有servlet的webapp。

只需2美分;)