Socket binding error

I have a test application that opens a socket, sends something through this socket, and then closes it. This is done in a loop for 5-10,000 times. The fact is that after 3,4000 iterations, I get an error of this type:

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

I even set that the socket will be used immediately, but the error persists

 try { out_server.write(m.ToByteArray()); socket_server.setReuseAddress(true); socket_server.close(); } catch(Exception e) { e.printStackTrace(); System.out.println(i+" unable to register with the server"); } 

What can I do to fix this?

+4
source share
7 answers

I think you can go too fast.

Most operating systems have a limit on the number of sockets that they can open at any given time, but this is actually worse.

When a socket is closed, it is placed at a specific timeout for a certain time. Usually this is twice as much as the time spent on the packet, and ensures that there are no packets on the network that are on the way to your socket.

Once this time is up, you can be sure that all packets on the network have already died. The socket is placed in this special state, so that packets that were online when you close it can be captured and thrown away if they arrive before they die.

I think that what happens in your case, sockets are not released as fast as you think.

We had a similar problem with code that opened up a lot of short sessions. For some time it worked fine, but then the hardware accelerated, allowing you to open up a lot of time over a certain period of time. This was manifested in the inability to open more sessions.

One way to check this is to make netstat -a from the command line and see how many sessions are really in standby.

If this is true, there are several ways to deal with it.

  • Reuse your sessions manually or by maintaining a connection pool.
  • enter a delay in each connection to try to stop the saturation point.
  • exit until you reach saturation, and then change your behavior, for example, run your connection logic inside the while statement, which retries up to 60 times with a two-second delay each time before completely abandoning. This allows you to work at full speed, slowing down only if there is a problem.

This last marker deserves some expansion. In fact, we used the delay strategy in our aforementioned application, which would gradually reduce the load on the resource provider if it complained, instead of 30 two-second delays, we chose a one-second delay, then two seconds, then four, etc.

The general process for the retreat strategy is as follows, and it can be used in any case where there may be a temporary lack of resource. The action mentioned in the pseudo code below will be opening the socket in your case.

 set maxdelay to 16 # maximum time period between attempts set maxtries to 10 # maximum attempts set delay to 0 set tries to 0 while more actions needed: if delay is not 0: sleep delay attempt action if action failed: add 1 to tries if tries is greater than maxtries: exit with permanent error if delay is 0: set delay to 1 else: double delay if delay is greater than maxdelay: set delay to maxdelay else: set delay to 0 set tries to 0 

This allows the process to run at full speed in the vast majority of cases, but backs off when errors occur, hoping that the resource time will be restored. Gradually increasing delays allows you to restore more serious resource constraints, and maximum attempts will catch what you would call permanent errors (or errors that take too long to recover).

+11
source

My suggestions:

  • start the socket after recording
  • add a tiny sleep (~ 50 ms?) at the end of the method described above.

@Pax has a good point on the state of the socket after that. Try your code, let it crash, then run netstat and parse it (or post here)

+2
source

What is the operating system? If you use windows, and I assume that you are, then there is a limit on the number of client connections you can have (this is configured using the MaxUserPort registry MaxUserPort , which is 4000 by default; see http://technet.microsoft. com / en-us / library / aa995661.aspx and http://www.tech-archive.net/Archive/Windows/microsoft.public.windows.server.general/2008-09/msg00611.html for details of changing it) . This is because you are initiating a socket located next to your client, and therefore the accumulation of sockets in TIME_WAIT state on your client is probably the cause of your problem.

Please note that solving the accumulation problem TIME_WAIT should NOT bother with the TCP stack parameters in order for the problem to disappear. TIME_WAIT exists for a very good reason, and deleting or shortening it is likely to cause new problems!

So, if you are on a Windows computer, the first step is to configure the MaxUserPort value so that you have more dynamic ports for outgoing connections. Further, if this does not help you, you can think about which side of the connection should end with TIME_WAIT (if you can control the protocol used in your connections). Friend, active close 'is one that ends with TIME_WAIT , so if you can change the situation for your servers to exit active closure, TIME_WAIT sockets will accumulate on the server, not on the client, and this MAY will be better for you ...

+2
source

I agree with others that you are running out of socket endpoints. However, what is not 100% crystal clear from you, for example, apparently, the exception comes from a call to connect () or bind (), which may be associated with some other high-level Java method.

It should also be emphasized that exhaustion of endpoints is not a limitation for a socket library, but rather a fundamental part of any TCP / IP implementation. You need to store information about old connections for a while in order to defer IP packets for the old connection.

setReuseAddress () matches the low-level SO_REUSEADDR socket option and applies only to the server when it executes the listen () function.

+1
source

I think this is the same as this question (and I'm related to my answer, which I think may help).

Java Bind Exception

0
source

If the sample code is actually how you execute the loop, you may have things in the wrong order.

The java docs for setReuseAddress say: behavior when SO_REUSEADDR is enabled or disabled after socket binding (see isBound ()) is undefined.

Try moving the call somewhere before binding () or connect ().

0
source

some time after using socket.close () will not immediately close the socket, and the loop will execute (in the loop it tries to connect the witrh socket to the same ip and port) much faster, therefore a null socket.

socket_server.close ();

socket_server = null;

Thanks Sunil Kumar Sahoo

0
source

All Articles