2011-11-29 61 views
2

我已经在Lua中编写了一个插件,用于通过UDP数据包(512字节)将播放器信息发送到远程服务器的游戏,远程服务器从数据包中读取数据并将所有播放器信息汇总一个xml文件(然后所有玩家都可以在网页上查看它们,以便他们可以看到彼此的当前状态)。DatagramSocket暂时停止接收数据包(Java)

我已经使用DatagramSocket编程服务器在Java中处理传入的数据包,但我注意到一些奇怪的行为。经过一段时间后,DatagramSocket似乎暂时停止接受连接约10-12秒,然后再次恢复正常行为(我不能看到任何异常)。客户端发送数据包的频率与发生此行为的速度之间肯定存在关系。如果我增加客户端的更新频率,DatagramSocket将会“尽快”失败。

值得一提的是,每接收到的数据包都会产生一个处理数据包中数据的线程。我在Linux上运行服务器,如果它有所作为!

有谁知道什么可能导致这种行为发生?

Andrew

+2

我的猜想是你的服务器端没有接收缓冲区空间。 – NPE

+0

太少细节(例如,您使用的是什么Linux风格,JVM和Java版本),以及一些代码会有所帮助;肯定为每个数据包产生一个新的线程是__bad__想法(使用线程池和/或队列)。无论如何,考虑UDP是不可靠的。 – Viruzzo

+0

我说错了一个线程被产生。我正在使用cachedThreadPool和ExecutorService来处理数据包。虽然我知道UDP是不可靠的,但它会突然停止丢弃数据包,特别是当我在本地主机上测试实现时,这是令人怀疑的。我会更深入地了解接收缓冲区的大小。 – Andrew

回答

3

UDP是一个网络协议,绝对没有交付保证。任何沿途任何网络组件(包括客户端和服务器PC本身)都可以决定因任何原因(例如高负载或网络拥塞)而丢弃数据包。

这意味着你必须花点时间找出发生丢包的位置。你可以使用诸如wireshark之​​类的东西来查看数据包是否到达服务器。

如果可靠传输比低延迟更重要,请切换到TCP。如果你坚持使用UDP,你将不得不允许数据包丢失,而不管你是否在这个特定的时间解决这个特定的问题。

+0

虽然可靠的交付不一定是一项重要的要求,但我最终转而使用TCP,问题似乎已经得到了解决。使用UDP的主要原因是因为客户端程序有一个很好的包发送UDP数据包,但我能够使用LuaSocket创建一个很好的解决方案。 – Andrew

3

我的猜想是你在服务器端的接收缓冲区空间不足。

您可能想重新审视您的设计:产生线程是一项相当昂贵的操作。这样做对于每个传入数据包都会导致吞吐量相对较低的系统,这很容易解释接收队列建立的原因。

而且,看Specifying UDP receive buffer size at runtime in Linux

附:我相信你已经知道UDP不能保证消息传递,所以我不会付诸实践。

+0

我们可以在android中做同样的事情吗?如果长时间操作后填充缓冲区,我们是否可以清除缓冲区?我的问题是听众在长时间工作后停止了 –

1

为每个UDP数据包启动一个线程是一个坏主意TM。 UDP服务器传统上被编码为简单的接收循环(毕竟你只需要一个套接字)。这样你可以避免线程的所有开销,同步以及没有的开销。

+0

+1。如果我在阅读原始问题方面做得更好,那么我会回答这个问题: - /。 – Barend