Tengo un requisito algo extraño para poder escuchar una serie de interfaces de red desde Java en una máquina Linux y determinar si una de ellas recibe paquetes UDP de una cierto tipo. Los datos de salida que necesito son la dirección IP de la interfaz en cuestión. ¿Hay alguna forma de hacer esto en Java?Java en Linux: escuchar mensajes de difusión en una dirección local encuadernada
Escuchar en la dirección de comodín (nuevo DatagramSocket (puerto)) no ayuda porque mientras obtengo los paquetes de difusión, no puedo determinar la dirección IP local de la interfaz que vinieron. Escuchar transmisiones mientras se está vinculado a una determinada interfaz (nuevo DatagramSocket (puerto, dirección)) no recibe los paquetes en absoluto. Este caso merece un ejemplo de código que muestra lo que estoy tratando de hacer:
Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface ni = (NetworkInterface) interfaces.nextElement();
Enumeration addresses = ni.getInetAddresses();
while (addresses.hasMoreElements()) {
InetAddress address = (InetAddress)addresses.nextElement();
if (address.isLoopbackAddress() || address instanceof Inet6Address)
continue; //Not interested in loopback or ipv6 this time, thanks
DatagramSocket socket = new DatagramSocket(PORT, address);
//Try to read the broadcast messages from socket here
}
}
También probé a inicializar el zócalo con la dirección de difusión construida sobre la base del principio de la IP real de la interfaz y el resto de acuerdo con la máscara de red correcta:
byte [] mask = { (byte)255, 0, 0, 0 };
byte[] addrBytes = InetAddress.getByName("126.5.6.7").getAddress();
for (int i=0; i < 4; i++) {
addrBytes[i] |= ((byte)0xFF)^mask[i];
}
InetAddress bcastAddr = InetAddress.getByAddress(addrBytes);
Eso sólo arroja una BindException al construir la DatagramSocket.
EDIT: BindException (java.net.BindException: No se puede asignar la dirección solicitada) de llamar al constructor de DatagramSocket con una emisión de direcciones (por ejemplo, 126.255.255.255) sólo viene con la última versión de Ubuntu 9.04 (probablemente no es Ubuntu, pero kernel sin embargo, problema específico de la conversión). Con Ubuntu 8.10 esto funcionó, al igual que con la versión de Red Hat (RHEL 4.x) con la que estoy lidiando.
Al parecer, no recibir los paquetes mientras está vinculado a un determinado IP local es el correct behaviour, aunque en Windows esto funciona. Necesito hacerlo funcionar en Linux (RHEL y Ubuntu). Con código C de bajo nivel hay una solución provisional setsockopt (SO_BINDTODEVICE) que no puedo encontrar en las API de Java. This exactamente no me hace reventar con optimismo, aunque :-)
Parece que el error no se ha solucionado en 10 años. ¡Loca! : D –