Obtenir les adresses IPv4 d’un adaptateur Ethernet sous Windows en utilisant Java 1.5

Problème

Mon système Windows possède plusieurs adaptateurs Ethernet. Étant donné le nom d’un adaptateur Ethernet, je dois trouver ses adresses IP.

Par exemple, la sortie de la commande ipconfig de mon système est la suivante:

 Ethernet adapter GB1: Connection-specific DNS Suffix . : IP Address. . . . . . . . . . . . : 0.0.0.0 Subnet Mask . . . . . . . . . . . : 0.0.0.0 Default Gateway . . . . . . . . . : Ethernet adapter SWITCH: Connection-specific DNS Suffix . : IP Address. . . . . . . . . . . . : 10.200.1.11 Subnet Mask . . . . . . . . . . . : 255.255.255.0 IP Address. . . . . . . . . . . . : 10.200.1.51 Subnet Mask . . . . . . . . . . . : 255.255.255.0 Default Gateway . . . . . . . . . : Ethernet adapter LAN: Connection-specific DNS Suffix . : IP Address. . . . . . . . . . . . : 10.1.2.62 Subnet Mask . . . . . . . . . . . : 255.255.254.0 IP Address. . . . . . . . . . . . : 10.1.2.151 Subnet Mask . . . . . . . . . . . : 255.255.254.0 Default Gateway . . . . . . . . . : 10.1.2.1 

Remarque: je n’ai pas besoin de me soucier des adaptateurs sans fil ou de tout autre type d’adaptateur. Je dois le faire pour les cartes Ethernet uniquement.

Pour ce système, je dois écrire une classe Java qui se comporte comme suit:

 C:>java NameToIp GB1 0.0.0.0 C:>java NameToIp SWITCH 10.200.1.11 10.200.1.51 C:>java NameToIp LAN 10.1.2.62 10.1.2.151 

Ce qui ne fonctionne pas

Utiliser java.net.NetworkInterface n’a pas aidé. Les méthodes getName () et getDisplayName () n’impriment pas les noms de connexion de l’adaptateur tels qu’ils apparaissent dans la sortie d’ ipconfig ou dans les connexions réseau Windows. Ils impriment les noms de périphérique réels à la place. Par exemple, considérons le code suivant:

 import java.util.Enumeration; import java.net.InetAddress; import java.net.NetworkInterface; import java.net.SocketException; import java.net.UnknownHostException; public class ListInterfaces { public static void main(Ssortingng[] args) throws SocketException, UnknownHostException { Enumeration nwInterfaces = NetworkInterface.getNetworkInterfaces(); while (nwInterfaces.hasMoreElements()) { NetworkInterface nwInterface = nwInterfaces.nextElement(); System.out.print(nwInterface.getName() + ": " + nwInterface.getDisplayName()); Enumeration addresses = nwInterface.getInetAddresses(); while (addresses.hasMoreElements()) { InetAddress address = addresses.nextElement(); System.out.print(" - " + address.getHostAddress()); } System.out.println(); } } } 

Cela imprime la sortie suivante:

 C:>java ListInterfaces lo: MS TCP Loopback interface - 127.0.0.1 eth0: Broadcom BCM5709C NetXtreme II GigE (NDIS VBD Client) # eth1: Broadcom BCM5709C NetXtreme II GigE (NDIS VBD Client) #2 - 10.200.1.11 - 10.200.1.51 eth2: Broadcom BCM5709C NetXtreme II GigE (NDIS VBD Client) #3 - 10.1.2.62 - 10.1.2.151 

Un hack laid qui fonctionne

J’ai écrit un hack laid qui extrait les adresses IP du nom de l’adaptateur spécifié à partir de la sortie de ipconfig . Voici le code.

 import java.util.ArrayList; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.InputStream; import java.io.IOException; public class NameToIp { public static ArrayList getIP(Ssortingng adapterName) throws IOException, InterruptedException { // Run the Windows 'ipconfig' command and get its stdout ProcessBuilder cmdBuilder = new ProcessBuilder("ipconfig"); Process process = cmdBuilder.start(); BufferedReader stdout = new BufferedReader( new InputStreamReader(process.getInputStream())); // Find the section for the specified adapter Ssortingng line; boolean foundAdapter = false; while ((line = stdout.readLine()) != null) { line = line.sortingm(); if (line.equals("Ethernet adapter " + adapterName + ':')) { foundAdapter = true; break; } } if (!foundAdapter) { process.waitFor(); throw new IOException("Adapter not found"); } // Find IP addresses in the found section ArrayList ips = new ArrayList(); while ((line = stdout.readLine()) != null) { // Stop parsing if we reach the beginning of the next // adapter section in the output of ifconfig if (line.length() > 0 && line.charAt(0) != ' ') { break; } line = line.sortingm(); // Extract IP addresses if (line.startsWith("IP Address.") || line.startsWith("IPv4 Address.")) { int colonIndex; if ((colonIndex = line.indexOf(':')) != 1) { ips.add(line.subssortingng(colonIndex + 2)); } } } process.waitFor(); return ips; } public static void main(Ssortingng[] args) throws IOException, InterruptedException { // Print help message if adapter name has not been specified if (args.length != 1) { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); Ssortingng prog = stack[stack.length - 1].getClassName(); System.err.println("Usage: java " + prog + " ADAPTERNAME"); System.err.println("Examples:"); System.err.println(" java " + prog +" \"Local Area Connection\""); System.err.println(" java " + prog +" LAN"); System.err.println(" java " + prog +" SWITCH"); System.exit(1); } ArrayList ips = getIP(args[0]); for (Ssortingng ip: ips) { System.out.println(ip); } } } 

Question

Y a-t-il une meilleure façon de résoudre ce problème?

Créez une DLL qui utilise l’API Windows pour interroger l’adresse Ethernet locale et utilisez JNI pour appeler la DLL.

Je vais répondre à ma propre question. Suite à la suggestion de SpaceTrucker , j’ai créé une classe Java en utilisant JNI comme suit.

 // NwInterface.java import java.util.ArrayList; public class NwInterface { public native ArrayList getAddresses(Ssortingng adapterName); static { System.loadLibrary("nwinterface"); } } 

Ensuite, j’ai créé la bibliothèque ‘nwinterface’ en C ++ comme suit.

 // nwinterface.cc #include  #include  #include  #include "NwInterface.h" #pragma comment(lib, "iphlpapi.lib") #pragma comment(lib, "advapi32.lib") bool GetFriendlyName(const char* adapterName, unsigned char* buffer, unsigned long size) { HKEY hKey; char key[1024]; _snprintf_s(key, sizeof key, _TRUNCATE, "SYSTEM\\CurrentControlSet\\Control\\Network\\" "{4D36E972-E325-11CE-BFC1-08002BE10318}\\%s\\Connection", adapterName); long ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE, key, 0, KEY_READ, &hKey); if (ret != ERROR_SUCCESS) { return false; } ret = RegQueryValueEx(hKey, "Name", 0, 0, buffer, &size); if (ret != ERROR_SUCCESS) { return false; } buffer[size - 1] = '\0'; return true; } JNIEXPORT jobject JNICALL Java_NwInterface_getAddresses(JNIEnv *env, jobject obj, jssortingng jAdapterName) { // Create a Java ArrayList object jclass arrayClass = env->FindClass("java/util/ArrayList"); jmethodID initMethod = env->GetMethodID(arrayClass, "", "()V"); jmethodID addMethod = env->GetMethodID(arrayClass, "add", "(Ljava/lang/Object;)Z"); jobject ips = env->NewObject(arrayClass, initMethod); // Get information about all adapters IP_ADAPTER_INFO adapterInfo[128]; unsigned long bufferSize = sizeof adapterInfo; unsigned long ret = GetAdaptersInfo(adapterInfo, &bufferSize); // If there is an error, return empty ArrayList object if (ret != NO_ERROR) { return ips; } // Iterate through the information of each adapter and select the // specified adapter for (PIP_ADAPTER_INFO adapter = adapterInfo; adapter != NULL; adapter = adapter->Next) { char friendlyName[1024]; ret = GetFriendlyName(adapter->AdapterName, (unsigned char *) friendlyName, sizeof friendlyName); if (ret == false) { continue; } const char *adapterName = env->GetSsortingngUTFChars(jAdapterName, 0); if (strncmp(friendlyName, adapterName, sizeof friendlyName) == 0) { for (PIP_ADDR_STRING addr = &(adapter->IpAddressList); addr != NULL; addr = addr->Next) { const char *ip = addr->IpAddress.Ssortingng; env->CallBooleanMethod(ips, addMethod, env->NewSsortingngUTF(ip)); } break; } } return ips; } 

Enfin, j’ai testé la classe Java en écrivant ce programme Java.

 // NameToIp2.java import java.util.ArrayList; public class NameToIp2 { public static void main(Ssortingng[] args) { // Print help message if adapter name has not been specified if (args.length != 1) { StackTraceElement[] stack = Thread.currentThread().getStackTrace(); Ssortingng prog = stack[stack.length - 1].getClassName(); System.err.println("Usage: java " + prog + " ADAPTERNAME"); System.err.println("Examples:"); System.err.println(" java " + prog +" \"Local Area Connection\""); System.err.println(" java " + prog +" LAN"); System.err.println(" java " + prog +" SWITCH"); System.exit(1); } // Use NwInterface class to translate NwInterface nwInterface = new NwInterface(); ArrayList ips = nwInterface.getAddresses(args[0]); for (Ssortingng ip: ips) { System.out.println(ip); } } } 

Les étapes pour comstackr et exécuter le programme sont les suivantes:

 javac NameToIp2.java javah -jni NwInterface cl /LD /EHsc /IC:\jdk1.5.0_13\include /IC:\jdk1.5.0_13\include\win32 nwinterface.cc 

Voici la sortie:

 C:>java NameToIp2 GB1 0.0.0.0 C:>java NameToIp2 SWITCH 10.200.1.11 10.200.1.51 C:>java NameToIp2 LAN 10.1.2.62 10.1.2.151