【问题标题】:Java TCP latencyJava TCP 延迟
【发布时间】:2012-04-01 06:26:37
【问题描述】:

我正在开发一个通过 WLAN 连接与 TCP Java 服务器通信的 Android 应用程序。 Android 应用程序是一个在屏幕上移动精灵的游戏。每当精灵移动时,AndroidClient 将其坐标发送到 Java 服务器,然后将数据发送到其他客户端(最多 4 个客户端)。服务器在单独的线程上处理每个客户端,大约每 20 毫秒发送一次数据更新,每个数据包大约包含 1-10 个字节。我在一个 70 Mbit 的网络上(我的无线网络上大约有 15 Mbit 有效)。

我遇到了连接不稳定的问题,并且遇到了大约 50-500 毫秒的延迟。每 10-30 个数据包。我已将 tcpNoDelay 设置为 true,从而停止了一致的 200 毫秒延迟,尽管它仍然滞后很多。由于我对 Android 和网络都很陌生,我不知道这是否可以预期。我还想知道 UDP 是否适合我的程序,因为我感兴趣的是快速发送更新而不是每个数据包都正确到达。

对于如何避免/解决此延迟问题的任何指导,我将不胜感激。关于如何实现这种客户端-服务器架构的一般提示也会受到欢迎。

【问题讨论】:

  • UDP 听起来确实是一个更好的选择。
  • 对于一个游戏,您可能想要添加一些预测(您可能已经看到了错误预测对某些游戏的影响)。
  • 使用 wireshark 或 tcpdump 捕获网络活动并在此处发布。
  • 听起来您的协议并非旨在以低延迟通过 TCP 工作。你能解释一下它是如何工作的吗?例如,它如何确保 ACK 捎带?将 tcpNoDelay 设置为 true 的事实在它应该受到伤害时有所帮助,这强烈表明您的协议从未设计用于 TCP 的低延迟。我的猜测是:1)您的编写代码可能很糟糕,并将部分应用程序级消息推送到传输层。 2)您的协议可能很糟糕,并且没有应用程序级别的确认来减少延迟。

标签: java sockets tcp latency


【解决方案1】:

在无线 LAN 中,您偶尔会看到丢包,这会导致数据包在延迟后重新传输。如果你想控制重传前的延迟,你几乎肯定必须使用 UDP。

【讨论】:

    【解决方案2】:

    您肯定想使用 UDP。对于一个游戏,你不在乎精灵的位置是否在短时间内不正确。所以 UDP 在这种情况下是理想的。

    另外,如果您对服务器代码有任何控制权,我不会为客户端使用单独的线程。如果您需要调用您无法控制并且可能阻塞的库(例如因为它们接触文件或尝试执行额外的网络通信),线程很有用。但它们很贵。它们消耗大量资源,因此它们实际上使事情变得

    因此,对于延迟和性能绝对至关重要的网络游戏服务器,我将只使用一个线程来处理具有状态的命令队列,然后确保您永远不会执行阻塞的操作。所以每个命令都按顺序处理,它的状态被评估和更新(就像激光爆炸与另一个物体相交)。如果命令需要阻塞(例如从文件中读取),那么您需要执行非阻塞读取并相应地设置该命令的状态,以便您的命令处理器永远不会阻塞。关键是命令处理器永远不会阻塞。它只会循环运行,但您必须以适当的方式调用 Thread.sleep(x) 以免浪费 CPU。

    对于客户端,当客户端提交命令时(例如他们发射激光或类似的东西),客户端将生成响应对象并将其插入到 Map 中,其中序列 id 作为键。然后它将发送带有序列 id 的请求,当服务器使用该 id 响应时,您只需在 Map 中查找响应对象并将响应解码为该对象。这意味着这允许您执行并发操作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-02
      • 2021-04-17
      相关资源
      最近更新 更多