Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

"java.net.BindException: Address already in use" when trying to do rapid Socket creation and destruction for load testing

I'm trying to load test a Java server by opening a large number of socket connections to the server, authenticating, closing the connection, then repeating. My app runs great for awhile but eventually I get:

java.net.BindException: Address already in use: connect

According to documentation I read, the reason for this is that closed sockets still occupy the local address assigned to them for a period of time after close() was called. This is OS dependent but can be on the order of minutes. I tried calling setReuseAddress(true) on the socket with the hopes that its address would be reusable immediately after close() was called. Unfortunately this doesn't seem to be the case.

My code for socket creation is:

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

But I still get this error:

java.net.BindException: Address already in use: connect after awhile.

Is there any other way to accomplish what I'm trying to do? I would like to for instance: open 100 sockets, close them all, open 200 sockets, close them all, open 300, etc. up to a max of 2000 or so sockets.

Any help would be greatly appreciated!

like image 716
bradforj287 Avatar asked Jan 16 '11 22:01

bradforj287


2 Answers

You are exhausing the space of outbound ports by opening that many outbound sockets within the TIME_WAIT period of two minutes. The first question you should ask yourself is does this represent a realistic load test at all? Is a real client really going to do that? If not, you just need to revise your testing methodology.

BTW SO_LINGER is the number of seconds the application will wait during close() for data to be flushed. It is normally zero. The port will hang around for the TIME_WAIT interval anyway if this is the end that issued the close. This is not the same thing. It is possible to abuse the SO_LINGER option to patch the problem. However that will also cause exceptional behaviour at the peer and again this is not the purpose of a test.

like image 86
user207421 Avatar answered Sep 28 '22 09:09

user207421


Not using bind() but setReuseAddress(true) is just weird, I hope you do understand the implications of setReuseAddress (and the point of). 100-2000 is not a great number of sockets to open, however the server you are attempting to connect to (since it looks the same addr/port pair), may just drop them w/ a normal backlog of 50.

Edit: if you need to open multiple sockets quickly (ermm port scan?), I'd very strongly recommend using NIO and connect()/finishConnect() + Selector. Opening 1000 sockets in the same thread is just plain slow. Forgot you may need finishConnect() either way in your code.

like image 40
bestsss Avatar answered Sep 28 '22 09:09

bestsss