4

我的 java 代码使用多个线程,每个线程运行一个 ServerSocket 并接受。这些线程使用 java 套接字相互通信。121个线程都运行良好,但是如果我用256个线程运行相同的代码,我会遇到这个错误:

java.net.SocketException: No buffer space available (maximum connections reached?): listen failed
    at java.net.PlainSocketImpl.socketListen(Native Method)
    at java.net.PlainSocketImpl.listen(Unknown Source)
    at java.net.ServerSocket.bind(Unknown Source)
    at java.net.ServerSocket.<init>(Unknown Source)
    at java.net.ServerSocket.<init>(Unknown Source)

我使用 windows xp sp3,有几个这样的帖子(here),但没有人针对这个问题发布解决方案。我还安装了一个 Windows 补丁来消除 TCP 连接的限制,但我没有解决我的问题。

4

4 回答 4

6

该消息说您可能连接不足。你检查过吗?您可以使用以下命令从命令行检查打开的套接字:

netstat -n

确保关闭两侧的所有套接字(在 finally 块中)。请记住,在您收到连接后,侦听套接字保持打开状态。不要太快地打开和关闭套接字(我会说它们不能立即重用,这可能与您的问题有关)。

为了获得更好的与套接字相关的性能,您可以使用 java.nio API,但它比 java.net 复杂得多。

于 2011-06-15T20:00:49.340 回答
4

我想这篇文章可能有你的答案。留下悬空的套接字会导致您达到最大值(这可能由 Windows 补丁无法修复的其他一些设置决定(例如 JVM 限制?)

附带说明一下,如果您使用这么多线程运行,那么使用 java.nio 而不是 java 的简单 Socket 和 ServerSocket 类很可能会更好。

这个站点是关于如何使用 java.nio 以及我如何学习它(以及查看Sun/Oracle 的 Java NIO API)的一个非常好的教程,来自使用简单的 Socket 和 ServerSocket 编程。

具体来说,对您的事业有帮助的是使用选择器,它允许您以与 C++ select() 调用与套接字一起使用的相同方式多路复用套接字 I/O。这意味着在您的套接字代码的核心,您可以减少大量线程处理套接字 I/O 的影响,并且只有一个线程直接与套接字交互。

于 2011-06-15T19:45:55.160 回答
2

我通过更改 ServerSocket 调用解决了问题。我的错误是将积压值设置得太高。我不需要该服务器侦听超过 5-6 个连接。我替换了: ServerSocket sock=new ServerSocket(port,500); 使用 ServerSocket sock=new ServerSocket(port,10); 现在一切正常!

于 2011-06-16T13:53:52.593 回答
1

不知道你具体在做什么,这只是一个猜测,但我会提供这个以防其他人看到类似的问题。我在尝试打开太多 OUTGOING 连接时看到了这个错误。通过减小缓冲区大小,您限制了连接线程打开的连接数(当您达到缓冲区限制时,它们将被拒绝)。如果您仍然获得足够的吞吐量,那是一个很好的解决方案。但是,另一种解决方案是增加可用传出连接的数量,这可能会解决您的问题并提供更好的吞吐量。

为此,您可以添加/修改 MaxUserPort 的注册表项。使用 regedit,找到 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Parameters 然后添加/修改键: MaxUserPort 输入 DWORD 和一个高值,如 65534(十进制)

有一篇关于 MaxuserPort 的usoft 技术文章

于 2017-02-22T16:48:29.083 回答