如何管理打开的数据报套接字以避免超过最大值?

Posted

技术标签:

【中文标题】如何管理打开的数据报套接字以避免超过最大值?【英文标题】:How do I manage open datagram sockets to avoid exceeding maximum? 【发布时间】:2016-01-14 17:24:23 【问题描述】:

我正在开发一些使用大量数据报套接字的代码。如果不仔细编码,这个数字可能会超过 jvm 允许的最大值。使用-Dsun.net.maxDatagramSockets=x 并不总是一种选择。我有这样的代码:

/* opening this channel will bring us to the limit--the maximum allowed by the JVM */
DatagramChannel channel1 = DatagramChannel.open();

/* do some stuff with channel1 */

/* Close channel1, and dereference it */
channel1.close();
channel1 = null;

/* this throws SocketException */
DatagramChannel channel2 = DatagramChannel.open();

分享DatagramChannels(即使用receive())可能是另一种选择,但知道这里发生了什么会很有用。

编辑:在实际代码中缩小问题范围后,我发现代码 sn-p 过于简化。这里的想法是,在达到DatagramChannels 的最大数量后,只有在另一个关闭时才会创建一个新的。但是,我处理的是SocketChannels 和DatagramChannels 的混合体,问题是即使我在处理完这些频道时在频道上调用close(),我必须确保频道我刚刚关闭的是DatagramChannel(而不是SocketChannel),然后再创建另一个。只是一个疏忽。

【问题讨论】:

你看过AutoCloseable[try-with-resources](http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html)吗?但我不明白为什么上面的channel2 应该在“channel1”已关闭时抛出异常...... 谢谢。 DatagramChannel 实现了Closeable,而try-with-resources 只是确保在try 块完成之前对资源调用close()(即finally 会做什么)。据我所知,问题中的代码与提供的代码相同。 对,那么如果channel1.close() 成功,为什么channel2 = DatagramChannel.open() 会抛出异常? 这正是我想知道的:)。我不知道这是因为垃圾收集延迟还是其他原因,以及可能建议解决它的方法。 垃圾回收无关。在该主题上,甚至不需要channel1 = null。我怀疑问题出在其他地方。以下 Ira 的建议可能有用。否则我会将DatagramChannel 包装在另一个类中,在那里我打开和关闭登录。我怀疑你没有关闭它们。请使用异常输出更新问题。 【参考方案1】:

处理此问题的最佳方法是使用一组可重复使用的池化套接字。我建议使用 netty 之类的框架,以避免必须自己实现所有细节。

【讨论】:

以上是关于如何管理打开的数据报套接字以避免超过最大值?的主要内容,如果未能解决你的问题,请参考以下文章

如何将数据从 Android 中的数据报套接字发送到 Node js 服务器?

查找最大 UDP 有效负载——python 套接字发送/发送

蓝牙:如何使用 Bluez 创建一个套接字以连接到具有特定 UUID 的服务?

如何等待任何套接字有数据?

数据报通道套接字不写 Java

如何拆分接收到的 boost asio udp 套接字联合数据报