How to Enumerate Ip Addresses of All Enabled Nic Cards from Java

How to enumerate IP addresses of all enabled NIC cards from Java?

This is pretty easy:

try {
InetAddress localhost = InetAddress.getLocalHost();
LOG.info(" IP Addr: " + localhost.getHostAddress());
// Just in case this host has multiple IP addresses....
InetAddress[] allMyIps = InetAddress.getAllByName(localhost.getCanonicalHostName());
if (allMyIps != null && allMyIps.length > 1) {
LOG.info(" Full list of IP addresses:");
for (int i = 0; i < allMyIps.length; i++) {
LOG.info(" " + allMyIps[i]);
}
}
} catch (UnknownHostException e) {
LOG.info(" (error retrieving server host name)");
}

try {
LOG.info("Full list of Network Interfaces:");
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
LOG.info(" " + intf.getName() + " " + intf.getDisplayName());
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
LOG.info(" " + enumIpAddr.nextElement().toString());
}
}
} catch (SocketException e) {
LOG.info(" (error retrieving network interface list)");
}

How to list all computers in network?

With the linked answers, you should be able to filter the available interfaces down to a few possible options (i.e. interfaces that are up, no loopback, have an IPv4 address, etc.).

To discover game hosts, you can do something like the following.

  • Let the game hosts listen for UDP broadcasts on a specific port.
  • Let the clients send out a UDP broadcast to the broadcast address of each of the remaining interfaces from above. The broadcast address can be determined by getBroadcast() in class InterfaceAddress.
  • The host replies, to let the client know it is waiting. When using UDP, the hosts IP is in the received DatagramPacket. When using TCP, the hosts IP can be determined from the Socket.
  • Then the client can use the address of the host to establish a direct connection and/or set up RMI.

Edit: I found this blog post, which includes code that does more or less what I described.

Safe method to get computer IP on UNIX using Java

Although a computer can have multiple network interfaces and different IPs, some of the interfaces can also be loopback or not running. To be "safe" you might even have to check names of the interface to see if you use the IP address from desired one.

Following method will give you a list of ip addresses from non-loopback, up and running interfaces.

 public static List<InetAddress> getIPAddress() throws SocketException {

List<InetAddress> ipAddresses = new ArrayList<InetAddress>();
Enumeration e;
e = NetworkInterface.getNetworkInterfaces();
while (e.hasMoreElements()) {
NetworkInterface ni = (NetworkInterface) e.nextElement();
if (ni.isLoopback() || !ni.isUp()) continue;

for (Enumeration e2 = ni.getInetAddresses(); e2.hasMoreElements(); ) {
InetAddress ip = (InetAddress) e2.nextElement();
ipAddresses.add(ip);
}
}
return ipAddresses;
}

Enumerate MAC addresses using only Java 6, or using only WMIC

What don't you just try to access WMI from java ? perhaps with jWMI – Query Windows WMI from Java

Getting the IP address of the current machine using Java

import java.net.DatagramSocket;
import java.net.InetAddress;

try(final DatagramSocket socket = new DatagramSocket()){
socket.connect(InetAddress.getByName("8.8.8.8"), 10002);
ip = socket.getLocalAddress().getHostAddress();
}

This way works well when there are multiple network interfaces. It always returns the preferred outbound IP. The destination 8.8.8.8 is not needed to be reachable.

Connect on a UDP socket has the following effect: it sets the destination for Send/Recv, discards all packets from other addresses, and - which is what we use - transfers the socket into "connected" state, settings its appropriate fields. This includes checking the existence of the route to the destination according to the system's routing table and setting the local endpoint accordingly. The last part seems to be undocumented officially but it looks like an integral trait of Berkeley sockets API (a side effect of UDP "connected" state) that works reliably in both Windows and Linux across versions and distributions.

So, this method will give the local address that would be used to connect to the specified remote host. There is no real connection established, hence the specified remote ip can be unreachable.

Edit:

As @macomgil says, for MacOS you can do this:

Socket socket = new Socket();
socket.connect(new InetSocketAddress("google.com", 80));
System.out.println(socket.getLocalAddress());

Java getting my IP address

The NetworkInterface class contains all the relevant methods, but be aware that there's no such thing as "my IP". A machine can have multiple interfaces and each interface can have multiple IPs.

You can list them all with this class but which interface and IP you choose from the list depends on what you exactly need to use this IP for.

(InetAddress.getLocalHost() doesn't consult your interfaces, it simply returns constant 127.0.0.1 (for IPv4))

How to Determine Internet Network Interface in Java

On my laptop (running Windows 7, with Virtual Box and it's network interface installed) the following code prints out the name of my wireless interface along with my local address. It uses a brute force approach at the end of the day, but will only try and actually connect to addresses that are considered to be the best candidates.

// 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;
}
}

(I've updated my answer with isReachable(...) based on Mocker Tim's answer.)

One thing to watch out for. socket.bind(...) would bark at me that the address and port is already in use if I tried to run my code too fast in succession like the connection isn't cleaned up fast enough. 8080 should be a random port maybe.

Get IPv4 addresses of an ethernet adapter in Windows using Java 1.5

I'll answer my own question. Following SpaceTrucker's suggestion, I created a Java class using JNI as follows.

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

public class NwInterface {

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

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

Then I created the 'nwinterface' library in C++ as follows.

// 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;
}

Finally, I tested the Java class by writing this Java program.

// 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);
}
}
}

The steps to compile and run the program are as follows:

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

Here is the output:

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


Related Topics



Leave a reply



Submit