2011-02-03 30 views
15

Para mi proyecto quería obtener una lista de todas las direcciones de broadcast disponibles para poder transmitir una solicitud y mi otra aplicación ubicada en otra computadora en la red no especificada respondería y obtendría la lista I (ahora usando la versión poco modificado con aporte de Mike) ocurrió esto:Detectando todas las direcciones de broadcast de la red disponible en Java

 

private ArrayList<InetAddress> getBroadcastAddresses() { 
     ArrayList<InetAddress> listOfBroadcasts = new ArrayList(); 
     Enumeration list; 
     try { 
      list = NetworkInterface.getNetworkInterfaces(); 

      while(list.hasMoreElements()) { 
       NetworkInterface iface = (NetworkInterface) list.nextElement(); 

       if(iface == null) continue; 

       if(!iface.isLoopback() && iface.isUp()) { 
        System.out.println("Found non-loopback, up interface:" + iface); 

        Iterator it = iface.getInterfaceAddresses().iterator(); 
        while (it.hasNext()) { 
         InterfaceAddress address = (InterfaceAddress) it.next(); 

         System.out.println("Found address: " + address); 

         if(address == null) continue; 
         InetAddress broadcast = address.getBroadcast(); 
         if(broadcast != null) listOfBroadcasts.add(broadcast); 
        } 
       } 
      } 
     } catch (SocketException ex) { 
      return new ArrayList<InetAddress>(); 
     } 

     return site; 
} 
 

funciona bastante bien para LAN reqular sin embargo cuando se trata de la LAN inalámbrica sólo se salta el segundo bucle while después de una etapa, porque de tener address es nulo, aunque cuando utilicé System.out.println(interfaceItem) solo para ver qué interfaces se están procesando, escribí el nombre de la LAN inalámbrica y mi IP correspondiente a la red

EDIT 1: This es la salida donde 172.16.1.104 es mi IP en la red inalámbrica. El problema aparece SOLAMENTE en mi notebook con Wifi. La salida proviene de mi computadora portátil, donde utilizo la mayoría de las conexiones inalámbricas y, a veces, uso UTP para conectarme con mi amigo. También hay una interfaz de red de VirtualBox en mi computadora portátil.

¿Podría decirme qué tiene de malo? ¡Gracias!

Nota: Así que resulta que esto podría ser un problema para mi portátil en particular y el código funciona para todos los demás en general, me encanta este tipo de problema :-) Parece un callejón sin salida pero gracias ayuda de todos modos :-)

¡Todavía te amo! ;-)

+0

Quizás, está bien tener solo una iteración de bucle interno, porque su NIC tiene solo una dirección de host IP. –

+0

Admito que no es necesario pasar por InterfaceAdresses ya que allí, como dices, debería ser solo uno o ninguno, pero eso funcionaría incluso ahora, ¿no? – Martin

+0

Sé que este ejemplo no se puede probar fácilmente para algunos de ustedes simplemente porque no tiene una red WiFi para probarlo pero, no obstante, no tiene sentido para mí por qué no funciona para redes inalámbricas. – Martin

Respuesta

5

Creo que tendrá que repetir en todas las direcciones y, además, comprobar si la dirección de difusión es null también.

Considere que es posible que también tenga direcciones que no espera que estén asignadas a la interfaz. En mi sistema Linux, con su código, la primera dirección que veo es una dirección IPv6, con una transmisión nula (ya que no existe una transmisión IPv6, aunque puede usar multidifusión para lograr el mismo efecto).

Debe eliminar por completo la sección 1st way del código. Cuando llame al continue;, irá a la siguiente interfaz en lugar de considerar la posibilidad de que haya dos direcciones.

La otra razón por la que siempre desea iterar todas las direcciones que pueden tener broadcasts es porque necesita considerar que puede tener direcciones en dos redes asignadas a una interfaz. Por ejemplo, puede tener una interfaz con 192.168.0.1/24 y 172.16.0.1/24 asignado.

Además, considere usar un Set para almacenar las direcciones de difusión para proteger contra el caso en el que podría tener dos direcciones en la misma subred asignada.

Finalmente, dado que el uso de las direcciones de difusión le restringirá a hablar solo a los hosts que tienen una dirección IP en la misma subred, es posible que falte a los hosts que no están configurados correctamente con la misma subred/máscara de red. Por lo tanto, es posible que desee considerar el uso de multidifusión para esto; puede usar IPv4 (o IPv6) todas las direcciones de multidifusión de nodos para llegar a todos los hosts en la subred, independientemente de la dirección configurada. (224.0.0.1 y FF01 :: 1, respectivamente)

Editar: También tiene un error en la 2nd way, relacionada con el uso del iterador.Como obtiene un nuevo .iterator() cada vez que gira alrededor del bucle for, tiene suerte de que no haya un bucle infinito aquí. he cambiado el código para esto, y funciona para mí:

$ cat Broadcasts.java 
import java.net.*; 
import java.util.*; 

public class Broadcasts 
{ 
    public static void main(String[] args) 
    { 
     HashSet<InetAddress> listOfBroadcasts = new HashSet<InetAddress>(); 
     Enumeration list; 
     try { 
      list = NetworkInterface.getNetworkInterfaces(); 

      while(list.hasMoreElements()) { 
       NetworkInterface iface = (NetworkInterface) list.nextElement(); 

       if(iface == null) continue; 

       if(!iface.isLoopback() && iface.isUp()) { 
        //System.out.println("Found non-loopback, up interface:" + iface); 

        Iterator it = iface.getInterfaceAddresses().iterator(); 
        while (it.hasNext()) { 
         InterfaceAddress address = (InterfaceAddress) it.next(); 
         //System.out.println("Found address: " + address); 
         if(address == null) continue; 
         InetAddress broadcast = address.getBroadcast(); 
         if(broadcast != null) 
         { 
          System.out.println("Found broadcast: " + broadcast); 
          listOfBroadcasts.add(broadcast); 
         } 
        } 
       } 
      } 
     } catch (SocketException ex) { 
      System.err.println("Error while getting network interfaces"); 
      ex.printStackTrace(); 
     } 

     // return listOfBroadcasts; 
    } 
} 

Otro problema es posible que encuentre es el try/catch alrededor básicamente el toda función, lo que haría que el código para detener si golpeara algo inesperado. Sería mejor rodear posibles puntos de falla con un try/catch y hacer algo sensato (como omitir la interfaz o dirección), pero no miré qué métodos pueden arrojar excepciones.

Editar 2: Leí mal el código; tu iterador estuvo bien. ;-) El problema (que señalé anteriormente) fue que su 1st way está cortocircuitando su 2nd way; dado que llega a la instrucción continue;, si la primera dirección es null, ni siquiera intenta recorrer todas ellas.

En cualquier caso, ejecute esas declaraciones println y publique los resultados si todavía tiene problemas.

Editar 3: OK, me rindo. ;-) Según la salida que publicaste, parece que te encuentras con un error en la clase NetworkInterface.

No sé si ayudaría a desactivar la opción preferIPv4Stack, pero debe probar eso. Busqué un poco para encontrar informes de errores que describen este comportamiento y no pude encontrar ninguno.

Ya que estás en Linux, siempre se puede tomar el enfoque de repliegue de los bombardeos a cabo y llamando a algo como:

/sbin/ip addr | perl -ne 'print "$1\n" if $_ =~ /inet.* brd ([0-9\.]*)/' 

... que debe devolver una lista de direcciones de difusión.

Editar 4: Acabo de notar en el Javadoc para NetworkInterface hay una llamada getSubInterfaces(). Tal vez deba llamar a esto para asegurarse de obtener todas las direcciones. (Que podría ayudar a colocar la salida de /sbin/ip addr y /sbin/ifconfig)

Editar 5: En cuanto a la generosidad se acaba de añadir. (¡Esta pregunta tiene más de un año!) ¿Podría alguien ejecutar el código en mi respuesta anterior (editado para que sea fácil de copiar/pegar/ejecutar) y decirme si funciona? Si no es así, edite la pregunta y anote los errores/problemas exactos.

+0

Utilicé el segundo enfoque originalmente y en este momento estoy tratando de hacerlo funcionar también, pero lo extraño es que cuando llego a la instancia de Wifi NetworkInterface, su lista de InterfaceAddresses devuelto por su método getInterfaceAddresses() muestra un tamaño de 1 pero cuando llega a for loop, itera y recupera aparentemente el único objeto en la lista, el objeto que obtiene es nulo aunque el método toString() de interfaceItem devuelve solo una dirección IP que es correcta. Eso es lo que me molesta ... – Martin

+0

@Martin, bueno, vi al menos un error en tu código. Ver mi versión fija. Descomenta las llamadas 'System.out' que agregué y publica los resultados si sigues teniendo problemas. – mpontillo

+0

me parece que su código es muy parecido al mío solo mientras que en lugar de for loop, no importa, los resultados siguen siendo los mismos, cuando presiono NetworkInterface inalámbrico y atraviesa el segundo mientras encuentra una dirección que es nula, entonces no continuar como it.hasNext() devuelve falso y vuelve al primer ciclo while – Martin

Cuestiones relacionadas