我正在开发一个Android应用程序,通过WLAN连接与TCP Java服务器通信。Android应用程序是一款可以在屏幕上移动精灵的游戏。每当sprite移动时,AndroidClient都会将其坐标发送到Java-server,然后Java-server将数据发送给其他客户端(最多4个客户端)。服务器在单独的线程上处理每个客户端,数据更新大约每20毫秒发送一次,每个包由大约1-10个字节组成。我在一个70Mbit的网络上(在我的无线上有大约15Mbit的有效)。
我遇到了连接不稳定的问题,并且遇到了大约50-500毫秒的延迟。每10-30个数据包。我已经将tcpNoDelay设置为true,停止了一致的200ms延迟,尽管它仍然滞后了很多。因为我对Android和网络都是新手,所以我不知道这是否是我所期望的。我还想知道UDP是否适合我的程序,因为我感兴趣的是快速发送更新,而不是每个正确到达的数据包。
如果有任何关于如何避免/解决此延迟问题的指导,我将不胜感激。关于如何实现这样的客户端-服务器体系结构的一般技巧也将受到欢迎。
发布于 2012-03-16 01:41:18
在无线LAN上,您偶尔会看到丢弃的数据包,这会导致数据包在一段延迟后重新传输。如果你想在重传之前控制延迟,你几乎肯定要使用UDP。
发布于 2016-02-02 08:12:58
您肯定想使用UDP。对于游戏来说,你并不关心精灵的位置是否在短时间内是不正确的。因此,UDP在这种情况下是理想的。
此外,如果您对服务器代码有任何控制,我不会对客户端使用单独的线程。如果您需要调用您无法控制且可能阻塞的库(例如,因为它们接触文件或尝试执行额外的网络通信),则线程非常有用。但它们是昂贵的。它们消耗了大量的资源,因此它们实际上使事情变得比它们本来可以做的更慢。
因此,对于延迟和性能绝对关键的网络游戏服务器,我将只使用一个线程来处理具有状态的命令队列,然后确保您永远不会执行阻塞的操作。因此,每个命令都是按顺序处理的,它的状态被评估和更新(就像一个与另一个对象相交的激光束)。如果命令需要阻塞(比如从文件中读取),那么您需要执行非阻塞读取,并相应地设置该命令的状态,以便您的命令处理器永远不会阻塞。关键是命令处理器永远不会阻塞。它将只在一个循环中运行,但您必须以适当的方式调用Thread.sleep(x),以免浪费CPU。
至于客户端,当客户端提交命令时(比如他们发射了激光之类的命令),客户端将生成一个响应对象,并将其插入到Map中,并使用序列id作为键。然后,它将发送带有序列id的请求,当服务器使用该id响应时,您只需在Map中查找响应对象,并将响应解码为该对象。这意味着您可以执行并发操作。
https://stackoverflow.com/questions/9724939
复制相似问题