“java.net.BindException:地址已经在使用中”,当尝试为负载测试进行快速套接字创建和销毁时

2022-09-01 11:03:10

我正在尝试通过打开与服务器的大量套接字连接,进行身份验证,关闭连接,然后重复来对Java服务器进行负载测试。我的应用程序运行了一段时间,但最终我得到了:

java.net.BindException: Address 已在使用中: connect

根据我阅读的文档,这样做的原因是,在调用 close() 后,已关闭的套接字在一段时间内仍然占用分配给它们的本地地址。这取决于操作系统,但可以在几分钟内完成。我尝试调用套接字,希望它的地址在被调用后立即可重用。不幸的是,情况似乎并非如此。setReuseAddress(true)close()

我的套接字创建代码是:

Socket socket = new Socket();
socket.setReuseAddress(true);
socket.connect(new InetSocketAddress(m_host, m_port));

但我仍然收到此错误:

java.net.BindException:地址已经在使用中:一段时间后连接。

有没有其他方法可以完成我想要做的事情?例如,我想:打开100个套接字,全部关闭,打开200个套接字,全部关闭,打开300个,等等,最多2000个左右的套接字。

任何帮助将不胜感激!


答案 1

通过在两分钟的TIME_WAIT时间段内打开许多出站套接字,可以节省出站端口的空间。您应该问自己的第一个问题是,这是否代表了一个现实的负载测试?一个真正的客户真的会这样做吗?如果没有,您只需要修改测试方法即可。

BTW SO_LINGER是应用程序在 close() 期间等待数据刷新的秒数。它通常为零。无论如何,如果这是发出收盘价的结束,则端口将在TIME_WAIT间隔内徘徊。这不是一回事。可以滥用SO_LINGER选项来修补问题。然而,这也会导致同行的特殊行为,同样这不是测试的目的。


答案 2

不使用 bind() 而是 setReuseAddress(true) 很奇怪,我希望你理解 setReuseAddress 的含义(以及要点)。100-2000 不是要打开的大量套接字,但是您尝试连接的服务器(因为它看起来是相同的 addr/端口对),可能会丢弃它们,而正常积压为 50。

编辑:如果您需要快速打开多个套接字(ermm端口扫描?),我强烈建议使用NIO和connect()/finishConnect()+选择器。在同一线程中打开1000个套接字非常慢。忘记了在你的代码中可能需要 finishConnect()


推荐