我正在尝试通过打开大量与服务器的套接字连接来加载测试Java服务器,验证,关闭连接,然后重复。我的应用运行了很长一段时间,但最终我得到了:
java.net.BindException:已在使用的地址: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个插座。
非常感谢任何帮助!
答案 0 :(得分:18)
通过在TIME_WAIT两分钟内打开许多出站套接字,您将耗尽出站端口的空间。您应该问自己的第一个问题是,这是否代表了一个真实的负载测试?真正的客户真的会这样做吗?如果没有,您只需修改测试方法。
BTW SO_LINGER是应用程序在close()期间等待刷新数据的秒数。它通常为零。如果这是发出结束的结束,端口将在TIME_WAIT间隔内闲逛。这不是一回事。可以滥用SO_LINGER选项来修补问题。然而,这也会导致同行的异常行为,这也不是测试的目的。
答案 1 :(得分:1)
不使用bind()但是setReuseAddress(true)很奇怪,我希望你能理解setReuseAddress的含义(以及它的意思)。 100-2000是不要打开的大量套接字,但是您尝试连接的服务器(因为它看起来是相同的地址/端口对),可能只是丢弃它们正常积压50岁。
编辑: 如果你需要快速打开多个套接字(ermm端口扫描?),我非常强烈建议使用NIO和connect()/ finishConnect()+ Selector。在同一个线程中打开1000个套接字只是很慢。 忘了你在代码中可能需要finishConnect()。
答案 2 :(得分:-2)
我认为您应该计划要用于连接的端口以供使用。我的意思是尝试使用给定的端口进行连接。如果连接失败(或者在您的情况下抛出异常),请尝试使用下一个端口号打开连接。
尝试将connect
语句包装在try/catch
。
这是一些伪代码,它传达了我认为可行的方法:
portNumber = x //where x is the first port number you will try
numConnections = 200 // or however many connections you want to open
while(numConnections > 0){
try{
connect(host, portNumber)
numConnections--
}catch(){}
portNumber++
}
此代码不包括诸如“当所有端口都在使用时会发生什么?”等极端情况。