2012-10-09 7 views
7

問題

私のWindowsシステムには複数のイーサネットアダプタがあります。イーサネットアダプタの名前が与えられたら、私はそのIPアドレスを見つける必要があります。例えばJava 1.5を使用してWindowsでイーサネットアダプタのIPv4アドレスを取得

、私のシステムのipconfigコマンドの出力は次のようになります。

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 

注:私はワイヤレスアダプタやアダプタの他の種類について悩む必要はありません。私はイーサネットアダプタのためだけにこれを行う必要があります。このシステムの

、私は以下に示すように振る舞い、Javaクラスを記述する必要があります。

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 

java.net.NetworkInterface助けていないを使用して

を動作しません何。 getName()getDisplayName()の方法では、出力のipconfigまたはWindowsネットワーク接続に表示されるアダプタ接続名は印刷されません。代わりに実際のデバイス名が表示されます。

を作品

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 

醜いハック私はのIPアドレスを抽出し、醜いハックを書いた:

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(String[] args) throws SocketException, UnknownHostException { 

     Enumeration<NetworkInterface> nwInterfaces = NetworkInterface.getNetworkInterfaces(); 

     while (nwInterfaces.hasMoreElements()) { 

      NetworkInterface nwInterface = nwInterfaces.nextElement(); 
      System.out.print(nwInterface.getName() + ": " + 
          nwInterface.getDisplayName()); 

      Enumeration<InetAddress> addresses = nwInterface.getInetAddresses(); 
      while (addresses.hasMoreElements()) { 
       InetAddress address = addresses.nextElement(); 
       System.out.print(" - " + address.getHostAddress()); 
      } 
      System.out.println(); 
     } 
    } 
} 

これは、次の出力は、出力します。たとえば、次のコードを検討指定されたアダプタ名は出力のipconfigから出力されます。ここにコードがあります。

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<String> getIP(String 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 
     String line; 
     boolean foundAdapter = false; 
     while ((line = stdout.readLine()) != null) { 
      line = line.trim(); 
      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<String> ips = new ArrayList<String>(); 
     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.trim(); 

      // Extract IP addresses 
      if (line.startsWith("IP Address.") || 
       line.startsWith("IPv4 Address.")) { 

       int colonIndex; 
       if ((colonIndex = line.indexOf(':')) != 1) { 
        ips.add(line.substring(colonIndex + 2)); 
       } 
      } 
     } 
     process.waitFor(); 

     return ips; 
    } 

    public static void main(String[] args) 
    throws IOException, InterruptedException 
    { 
     // Print help message if adapter name has not been specified 
     if (args.length != 1) { 
      StackTraceElement[] stack = Thread.currentThread().getStackTrace(); 
      String 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<String> ips = getIP(args[0]); 
     for (String ip: ips) { 
      System.out.println(ip); 
     } 
    } 
} 

質問

は、この問題を解決するための良い方法はありますか?

+0

JavaはWindowsのNIC、Unixの互換性があるに設計されているように見えます名前は明確に定義されておらず、プラットフォームごとに異なります。 –

答えて

0

私は自分の質問に答えます。 SpaceTrucker's suggestionに続いて、JNIを使​​用してJavaクラスを作成しました。

// NwInterface.java 
import java.util.ArrayList; 

public class NwInterface {  

    public native ArrayList<String> getAddresses(String adapterName);  

    static 
    { 
     System.loadLibrary("nwinterface"); 
    }   
} 

次に、「nwinterface」ライブラリをC++で次のように作成しました。

// nwinterface.cc 
#include <iostream> 
#include <winsock2.h> 
#include <iphlpapi.h> 
#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, 
                 jstring jAdapterName) 
{ 
    // Create a Java ArrayList object 
    jclass arrayClass = env->FindClass("java/util/ArrayList"); 
    jmethodID initMethod = env->GetMethodID(arrayClass, "<init>", "()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->GetStringUTFChars(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.String; 
       env->CallBooleanMethod(ips, addMethod, env->NewStringUTF(ip)); 
      } 
      break; 
     } 

    } 

    return ips; 
} 

最後に、このJavaプログラムを作成してJavaクラスをテストしました。次のようにプログラムをコンパイルして実行する

// NameToIp2.java 
import java.util.ArrayList; 

public class NameToIp2 
{ 
    public static void main(String[] args) 
    { 
     // Print help message if adapter name has not been specified 
     if (args.length != 1) { 
      StackTraceElement[] stack = Thread.currentThread().getStackTrace(); 
      String 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<String> ips = nwInterface.getAddresses(args[0]); 
     for (String ip: ips) { 
      System.out.println(ip); 
     } 
    } 
} 

手順は次のとおりです。

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

ここで出力されます:

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 
3

Windows APIを使用してローカルのイーサネットアドレスを照会し、JNIを使​​用してdllを呼び出すdllを作成します。

+0

[JNA](https://github.com/twall/jna)。 –

+0

私は実際にJNIを避けようとしていたので、この問題の純粋なJavaソリューションがあれば探っていました。しかし、この質問に対する回答の不足から、これを行うための純粋なJavaの方法がないように思われるので、私はあなたの提案に進み、この問題を解決するためのJNIソリューションを実装しました。別の答えとして投稿しました。私はおそらく正しい答えとして私の答えを選ぶでしょう、このポストへの将来の訪問者が正解で完全なコードを見ることができるように、あなたの答えに本当に感謝し、私はそれをupvotedしました。ありがとう! –

+0

私はちょうど私がいつもMACアドレスについて考えていることに気づいた。しかし、この答えがIPv4アドレスにも当てはまることは良いことです。 – SpaceTrucker

関連する問題