Search code examples
javasocketsip

Getting the IP address of the current machine using Java


I am trying to develop a system where there are different nodes that are run on different system or on different ports on the same system.

Now all the nodes create a Socket with a target IP as the IP of a special node known as a bootstrapping node. The nodes then create their own ServerSocket and start listening for connections.

The bootstrapping node maintains a list of Nodes and returns them on being queried.

Now what I need is the node must register its IP to the bootstrapping node. I tried using cli.getInetAddress() once the client connects to the ServerSocket of bootstrapping node but that didn't work.

  1. I need the client to register its PPP IP if available;
  2. Otherwise the LAN IP if available;
  3. Otherwise it must register 127.0.0.1 assuming its the same computer.

Using the code:

System.out.println(Inet4Address.getLocalHost().getHostAddress());

or

System.out.println(InetAddress.getLocalHost().getHostAddress());

My PPP Connection IP address is: 117.204.44.192 but the above returns me 192.168.1.2

EDIT

I am using the following code:

Enumeration e = NetworkInterface.getNetworkInterfaces();
while(e.hasMoreElements())
{
    NetworkInterface n = (NetworkInterface) e.nextElement();
    Enumeration ee = n.getInetAddresses();
    while (ee.hasMoreElements())
    {
        InetAddress i = (InetAddress) ee.nextElement();
        System.out.println(i.getHostAddress());
    }
}

I am able to get all the IP addresses associated all NetworkInterfaces, but how do I distinguish them? This is the output I am getting:

127.0.0.1
192.168.1.2
192.168.56.1
117.204.44.19

Solution

  • 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());