DatagramChannel.close () utrzymuje port otwarty w systemie Windows

Wdrażam proces Discover, który:

Otwórz gniazdo UDP, aby nasłuchiwać odpowiedzi transmisji na danym porcieWyślij kilka żądań (i oczekuj późniejszej odpowiedzi)Zamknij gniazdo UDP po upływie określonego czasu

Pierwsze połączenie działa. Ale inne wywołanie powoduje błąd wiązania. Adres już używany: bind

Używam Windows 7. Wykonałem kilka testów i znalazłem to po channel.close (); Netstat nadal daje:

netstat -a -b -sp udp | grep 55224

UDP 0.0.0.0:55224:

Tak więc port udp jest nadal otwarty na poziomie systemu operacyjnego

Szukałem w internecie i może to być wyciek na poziomie OS:Niektóre pytania dotyczące gniazd datagramowych java

Uruchomiłem 2 testy, jeden używając kanału NIO i jeden bez (z testu znalezionego w sieci). Odtwarzam mój błąd w wersji NIO, ale działa, jeśli nie używam NIO.

Ktoś może mi wskazać, jak mogę sprawić, by działało z NIO. Docelową platformą jest Android, w którym nie mamt wan• aby zawsze słuchać transmisji, ale tylko przez powtarzalny okres czasu.

GNIAZDO TESTOWE
    public void testConnectCloseWithSocket() {
    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;
            try {
                Thread.sleep(50);
            } catch (InterruptedException e1) {


            }
            i--;
        }
    }
    System.out.println("end...");

}
GNIAZDO WYNIKÓW <

start ... Błąd (przy = 1319) (oczekiwanie = 0 ms): Adres już używany: Nie można powiązać

Błąd (przy = 1438) (oczekiwano = 0 ms): Adres już używany: Nie można powiązać

Błąd (przy = 1587) (oczekiwano = 0 ms): adres już używany: nie można powiązać

Błąd (przy = 1740) (oczekiwanie = 0 ms): Adres już używany: Nie można powiązać

koniec...

Dostałem pewne błędy, ale gniazdo zostało poprawnie zamknięte ... co jest w porządku dla moich potrzeb

TEST Z KANAŁEM
    public void testConnectCloseWithChannel() {
    long tCumulative = 0;
    int errAt = -1;
    System.out.println("start...");
    for (int i = 0; i < 4000; i++) {
        try {
            errAt = i;
            Selector selector = Selector.open();
            DatagramChannel channel = DatagramChannel.open();
            channel.configureBlocking(true);
            channel.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), 9005));
            SelectionKey clientKey = channel.register(selector, SelectionKey.OP_READ);
            clientKey.cancel();
            channel.close();

            //success at last
            tCumulative = 0;

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

            tCumulative+=50;
            try {
                Thread.sleep(tCumulative);
            } catch (InterruptedException e1) {


            }
            i--;
        }
    }
    System.out.println("end...");

}

UWAGA: To, że channel.register jest komentowane, test działa.

WYNIK Z KANAŁEM

start ... Błąd (at = 0) (oczekiwanie = 0 ms): Błąd zerowy (at = 0) (oczekiwanie = 50 ms): Adres już w użyciu: bind

Błąd (at = 0) (oczekiwano = 100 ms): Adres już używany: bind

Błąd (at = 0) (oczekiwanie = 150 ms): Adres już używany: bind ...

Dzięki za pomoc

questionAnswers(2)

yourAnswerToTheQuestion