DatagramChannel.close () hält den Port unter Windows offen
Ich implementiere einen Discover-Prozess, der:
Öffnen Sie einen UDP-Socket, um auf Broadcast-Antworten an einem bestimmten Port zu wartenSenden Sie einige Anfragen (und erwarten Sie eine spätere Antwort)Schließen Sie den UDP-Socket nach einer bestimmten ZeitDer erste Anruf funktioniert. Bei anderen Aufrufen tritt jedoch ein Bindefehler auf. Bereits verwendete Adresse: binden
Ich verwende Windows 7. Ich habe einige Tests durchgeführt und festgestellt, dass nach einem channel.close (); Netstat gibt noch:
netstat -a -b -sp udp | grep 55224
UDP 0.0.0.0:55224:
Der udp-Port ist also immer noch auf Betriebssystemebene geöffnet
Ich habe im Internet gesucht und es könnte ein Leck auf Betriebssystemebene sein:Einige Java Datagram Socket Fragen
Ich habe 2 Tests durchgeführt, einen mit NIO-Kanal und einen ohne (aus einem Test im Internet). Ich reproduziere meinen Fehler mit der NIO-Version, aber es funktioniert, wenn ich NIO nicht verwende.
Ich jeder kann mir zeigen, wie ich es mit NIO machen kann. Die Zielplattform ist Android, auf der ich arbeitet wan
t immer auf Sendung zu hören, aber nur für sich wiederholende Zeit.
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...");
}
ERGEBNISSTECKDOSE <start ... Error (at = 1319) (waited = 0ms): Adresse wird bereits verwendet: Kann nicht binden
Fehler (um = 1438) (gewartet = 0 ms): Adresse wird bereits verwendet: Kann nicht gebunden werden
Fehler (um = 1587) (gewartet = 0 ms): Bereits verwendete Adresse: Kann nicht gebunden werden
Fehler (um = 1740) (gewartet = 0 ms): Bereits verwendete Adresse: Kann nicht gebunden werden
Ende...
Ich habe einige Fehler bekommen, aber die Steckdose wurde richtig geschlossen ... was für meine Bedürfnisse ok ist
TEST MIT KANAL 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...");
}
HINWEIS: Wenn das channel.register kommentiert ist, funktioniert der Test.
Ergebnis mit Kanalstart ... Fehler (at = 0) (waited = 0ms): null Fehler (at = 0) (waited = 50ms): Bereits verwendete Adresse: bind
Fehler (at = 0) (waited = 100ms): Adresse wird bereits verwendet: bind
Fehler (at = 0) (waited = 150ms): Adresse wird bereits verwendet: bind ...
Danke für jede Hilfe