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 czasuPierwsze 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.
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ŁEMstart ... 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