3

Following code can reproduce the issue: int errAt = -1;

  try {
    System.out.println("start...");
    for (int i = 0; i < 4000; i++) {
      errAt = i;
      DatagramSocket result = new DatagramSocket(null);
      result.bind(new InetSocketAddress(InetAddress.getLocalHost(), 9005));
      result.close();
      //System.out.println(i);
    }

  } catch (Exception e) {
    System.out.println("Error: " + e.getMessage());
    System.out.println("ErrAt: " + errAt);
    e.printStackTrace();
  } finally {
    System.out.println("end...");
  }

In my PC, I'll see "java.net.BindException: Address already in use: Cannot bind" exception after run 2k+ times.

I'm not sure, is this means that the close method didn't close the native socket immediately?

J2.NETe
  • 71
  • 1
  • 5

3 Answers3

2

This code works on my Mac even if I set it to run 40,000 iterations. I think the likely problem here is that the socket isn't being closed immediately on Windows but then again you are trying to do thousands of iterations within the space of probably milliseconds.

The following code will continually retry and sleep a small amount of time to let you see if its a delay problem where the socket would be closed within some space of time:

    long tCumulative = 0;
    int errAt = -1;
    System.out.println("start...");
    for (int i = 0; i < 4000; i++) {
        try {
            errAt = i;
            DatagramSocket result = new DatagramSocket(null);
            result.bind(new InetSocketAddress(InetAddress.getLocalHost(), 9005));
            result.close();

            //success at last
            tCumulative = 0;

        } catch (Exception e) {
            System.out.println("Error (at="+errAt+") (waited="+tCumulative+"ms): " + e.getMessage());

            tCumulative+=50;
            Thread.sleep(50);
            i--;
        }
    }
    System.out.println("end...");
AntonyM
  • 1,602
  • 12
  • 12
  • The socket isn't being closed immediately on Windows indeed. – J2.NETe Dec 29 '11 at 05:48
  • Given that you can run the code about 2000 times before it fails probably the most likely issue is either that either the closing and rebinding is a race condition (i.e. Windows is doing it pretty quickly but after 2000 times you hit a case where you are trying to rebind before it has closed it) or you are running out of windows resources because its not clearing them fast enough. Do you find that when it fails it waits for a tiny bit but then works OK for another ton of sockets before or after it fails does it seem to have to wait a while for each socket to be closed? – AntonyM Dec 29 '11 at 17:51
  • The reason I ask the above is because if it seems to fail after about 2000 sockets but then work OK for another 2000 or so sockets after you've waited for 50ms then its likely just a race condition. If instead it fails after 2000 sockets and you find that you are then limited to maybe closing and rebinding one socket every few hundred millis or seconds then this would suggest that Windows is cleaning up the resources only after a timeout. If its the first thats OK - you just need to wait + retry if it happens, if the second you might want to look for registry settings about socket cleanup. – AntonyM Dec 29 '11 at 17:56
1

It is not clear what you are trying to do, but one way to get around the problem of a UDP port still being in use is to set the "reuse address" option before you bind.

Reference: How to set reuse address option for a datagram socket in java code?

Community
  • 1
  • 1
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
1

If you create the socket but then get e.g. a BindException you aren't closing the socket. It should be closed in a finally {} block.

It is difficult to see the point of this test. Normal UDP programs open one DatagramSocket and leave it open for the life of the process. No sane program would churn through thousands of UDP sockets.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 1
    @SunilKumarSahoo Please see the code yourself. If an exception is thrown by the bind() call, the socket is *not* closed. – user207421 Dec 30 '11 at 00:51
  • @downvoters Please explain, unless you want it to be taken as mere site vandalism. – user207421 Oct 03 '12 at 12:04
  • @SuniKumarSahoo EJP answer may not be the root cause of your problem but it is a legitimate possible root cause. The whole reason try-with-resource was added to Java is to help folks correctly work with closable resources like sockets. See http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html for more info. – buzz3791 Apr 18 '13 at 14:51