2011-12-11 21 views
11

¿Cómo se determina qué interfaz de red está conectada a Internet utilizando Java? Por ejemplo, corroCómo determinar la interfaz de red de Internet en Java

InetAddress.getLocalHost().getHostAddress(); 

y dentro de Eclipse Esto devuelve exactamente lo que pretendo, 192.168.1.105. Sin embargo, si empaqueté esto en un archivo jar y ejecuté el programa, el código devuelve 169.254.234.50. Al analizar esto, descubrí que esta es la dirección IP de una interfaz del Adaptador Virtual Ethernet de VMware en mi máquina.

¿Hay alguna manera de determinar la interfaz conectada a Internet, pero al mismo tiempo mantener la portabilidad de mi código?

Comparación de Interfaces

Interface [net4]

display name : Intel(R) Centrino(R) Ultimate-N 6300 AGN 
MTU   : 1500 
loopback  : false 
point to point: false 
up   : true 
virtual  : false 
multicast  : true 
HW address : 00 24 D7 2C 5F 70 
INET address (IPv4): 192.168.1.105 
    host name   : MyComputer 
    canonical host name : MyComputer 
    loopback   : false 
    site local   : true 
    any local   : false 
    link local   : false 
    multicast   : false 
    reachable   : true 

Interface [eth5]

display name : VMware Virtual Ethernet Adapter for VMnet1 
MTU   : 1500 
loopback  : false 
point to point: false 
up   : true 
virtual  : false 
multicast  : true 
HW address : 00 50 56 C0 00 01 
INET address (IPv4): 169.254.234.50 
    host name   : MyComputer 
    canonical host name : MyComputer 
    loopback   : false 
    site local   : false 
    any local   : false 
    link local   : true 
    multicast   : false 
    reachable   : true 

Hay una tercera interfaz de VMware con sitio local = true y enlace local = falso, entonces esos campos aren ' También ayuda.

+0

¿está ejecutando el archivo JAR dentro de una máquina virtual de la máquina virtual es su propio entorno, con su propia interfaz de red, que es? lo que devuelve Java. – blackcompe

+0

N o, esto está en una máquina con Windows 7. Sin embargo, tengo VMWare instalado y creo que esta es la interfaz que usa para comunicarse con la máquina virtual. No estoy seguro de por qué Java elige esta interfaz como la predeterminada. Este comportamiento es idéntico en la computadora de mi compañero de cuarto (Windows 7, VMWare instalado) –

+0

@CavynVonDeylen Consulte mi respuesta actualizada. El código que publiqué solo imprime mi interfaz de red real, mientras tengo la red de Virtual Box instalada y habilitada. –

Respuesta

17

En mi computadora portátil (con Windows 7, con Virtual Box y su interfaz de red instalada) el siguiente código imprime el nombre de mi interfaz inalámbrica junto con mi dirección local. Utiliza un enfoque de fuerza bruta al final del día, pero solo intentará conectarse a las direcciones que se consideran mejores candidatos.

// iterate over the network interfaces known to java 
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces(); 
OUTER : for (NetworkInterface interface_ : Collections.list(interfaces)) { 
    // we shouldn't care about loopback addresses 
    if (interface_.isLoopback()) 
    continue; 

    // if you don't expect the interface to be up you can skip this 
    // though it would question the usability of the rest of the code 
    if (!interface_.isUp()) 
    continue; 

    // iterate over the addresses associated with the interface 
    Enumeration<InetAddress> addresses = interface_.getInetAddresses(); 
    for (InetAddress address : Collections.list(addresses)) { 
    // look only for ipv4 addresses 
    if (address instanceof Inet6Address) 
     continue; 

    // use a timeout big enough for your needs 
    if (!address.isReachable(3000)) 
     continue; 

    // java 7's try-with-resources statement, so that 
    // we close the socket immediately after use 
    try (SocketChannel socket = SocketChannel.open()) { 
     // again, use a big enough timeout 
     socket.socket().setSoTimeout(3000); 

     // bind the socket to your local interface 
     socket.bind(new InetSocketAddress(address, 8080)); 

     // try to connect to *somewhere* 
     socket.connect(new InetSocketAddress("google.com", 80)); 
    } catch (IOException ex) { 
     ex.printStackTrace(); 
     continue; 
    } 

    System.out.format("ni: %s, ia: %s\n", interface_, address); 

    // stops at the first *working* solution 
    break OUTER; 
    } 
} 

(He actualizado mi respuesta con isReachable(...) basado en Mocker Tim's respuesta.)

Una cosa a tener en cuenta.socket.bind(...) me ladraría que la dirección y el puerto ya están en uso si traté de ejecutar mi código demasiado rápido en sucesión como si la conexión no se limpiara lo suficientemente rápido. 8080 debe ser un puerto aleatorio tal vez.

+0

Esto devuelve la interfaz que quiero y las dos interfaces VMWare en mi computadora. La interfaz que quiero es la primera, pero realmente no quiero confiar en que eso sea cierto todo el tiempo. –

+0

@CavynVonDeylen Si puede describir su caso de uso, podríamos proponer * algún tipo * de solución. Sin embargo, no habrá una forma * limpia * de hacer esto. Mi primera suposición es que debe filtrar las direcciones por su IP: descartar direcciones * no * comenzando con '192.168.1'. Sí, es * bárbaro *. –

+0

Gracias! Este código funciona para mí. Me sorprende que Java no ofrezca una manera fácil de hacerlo, ya que creo que esto sería un problema bastante común. Tal vez en Java 8. –

5

Eche un vistazo a Retrieving Network Interfaces y Listing Network Interface Addresses en el tutorial de Java.

Si tiene varias interfaces de red en funcionamiento, debe seleccionar mediante programación la interfaz de red que debe usar su programa.

ACTUALIZACIÓN:

que he encontrado la pregunta que es similar a la suya.
Ver la respuesta al how-to-check-if-internet-connection-is-present-in-java.

ACTUALIZACIÓN 2:

mi humilde opinión usted debe hacer lo siguiente en su programa:

  1. Buscar todas las interfaces de red IPv4 de la máquina que el programa se está ejecutando en;
  2. Pregunte al usuario cuál de ellos debería usar su programa;
  3. Use la interfaz que el usuario señaló.
+1

Puedo obtener una lista extravagante de todas las interfaces en mi máquina, pero no he encontrado ninguna forma de determinar programáticamente qué interfaz está conectada a Internet. Asumo que si tuviera que codificar "net4" por ejemplo, que es la interfaz correcta en mi máquina, esto no se aplicaría a otras computadoras que ejecutan mi programa. –

+0

@CavynVonDeylen Ver mi actualización. – MockerTim

1

que estaba teniendo el mismo problema, y ​​se acercó con esta solución (no tan completa como la respuesta, pero necesitaba algo que no intente conectarse a internet.

Basado en OUI conocido por mac direcciones: http://standards-oui.ieee.org/oui.txt

yo hicimos una comprobación rápida (podría optimizarse con la lógica binaria)

private static boolean isVmwareMac(byte[] mac) { 
    byte invalidMacs[][] = { 
      {0x00, 0x05, 0x69},    //VMWare 
      {0x00, 0x1C, 0x14},    //VMWare 
      {0x00, 0x0C, 0x29},    //VMWare 
      {0x00, 0x50, 0x56}    //VMWare 
    }; 

    for (byte[] invalid: invalidMacs){ 
     if (invalid[0] == mac[0] && invalid[1] == mac[1] && invalid[2] == mac[2]) 
      return true; 
    } 

    return false; 
} 
Cuestiones relacionadas