DatagramChannel.close () mantém a porta aberta no Windows
Estou implementando um processo de Descoberta que:
Abra um soquete UDP para ouvir a resposta de transmissão em uma determinada portaEnvie algumas solicitações (e espere uma resposta posterior)Feche o soquete UDP após um determinado período de tempoA primeira chamada funciona. Mas outra chamada recebe um erro de ligação. Endereço já em uso: bind
Estou executando o Windows 7. Fiz alguns testes e descobri que depois de um channel.close (); O Netstat ainda dá:
netstat -a -b -sp udp | grep 55224
UDP 0.0.0.0:55224:
Então a porta do udp ainda está aberta no nível do SO
Eu procurei na web e pode ser um vazamento no nível do SO:Algumas perguntas do soquete do datagrama de java
Eu corri 2 testes usando um canal NIO e um sem (a partir de um teste encontrado na web). Eu reproduzo meu erro com a versão NIO, mas funciona se eu não usar o NIO.
Qualquer um pode me mostrar como posso fazer isso funcionar com a NIO. A plataforma de destino é o Android, onde eu nãot wan
t sempre ouvir a transmissão, mas apenas por um período de tempo repetitivo.
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...");
}
RESULTADO SOCKET <start ... Erro (at = 1319) (esperado = 0ms): Endereço já em uso: não é possível ligar
Erro (at = 1438) (esperado = 0ms): Endereço já em uso: não é possível ligar
Erro (at = 1587) (esperado = 0ms): Endereço já em uso: não é possível ligar
Erro (at = 1740) (esperado = 0ms): endereço já em uso: não é possível vincular
fim...
Eu recebi alguns erros, mas o soquete foi fechado corretamente ... que é oki para minhas necessidades
TESTE COM CANAL 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...");
}
NOTA: É o channel.register é comentado o teste funciona ..
RESULTADO COM CANALstart ... Erro (at = 0) (esperado = 0ms): null Erro (at = 0) (esperado = 50ms): Endereço já em uso: bind
Erro (at = 0) (esperado = 100ms): Endereço já em uso: bind
Erro (at = 0) (esperado = 150ms): Endereço já em uso: bind ...
Obrigado por qualquer ajuda