56

I'm writing a simple networking app. I need to know the real IP of my machine on the network, like 192.168.1.3 . getLocalHost returns 127.0.0.1 (on Linux, I don't know if it is the same on windows). How to do it?

peterh
  • 11,875
  • 18
  • 85
  • 108
gotch4
  • 13,093
  • 29
  • 107
  • 170
  • 1
    In my windows, System.out.println(InetAddress.getLocalHost().getHostAddress()); prints 10.50.16.136 – Kannan Ekanath Mar 04 '10 at 17:31
  • Interesting ... correct answer although it's not working? – sfussenegger Mar 04 '10 at 17:55
  • This is very common on SO, the incorrect answered gets marked as answered. – Steve Kuo Mar 04 '10 at 17:57
  • 2
    @sfussenegger 127.0.1.1 is a Debian thing (which Ubuntu is derived from). IIRC, you will get it if you are using DHCP. This allows reporting a fixed IP address (I believe this is necessary for the smooth running of GNOME). So 127.0.1.1 is a "real IP" address. (BTW: 192.168.* is non-internet IP address.) – Tom Hawtin - tackline Mar 04 '10 at 18:39
  • @tom yeah, I know what it is. I'm just wondering how this is the correct answer to the question ("I need to know the real ip of my machine on the network"). – sfussenegger Mar 04 '10 at 18:44
  • @sfussenegger the *real* answer would be to find a way to query each network interface for its addresses. I don't know a way to do that in Java, but that's how I do it in C. – jdizzle Mar 04 '10 at 22:48
  • @jdizzle Why would that be the real answer? The question was how to determine the "the real ip of my machine on the network". How is a list of IPs helpful in answering this question which states that there is only interest in one IP that's used for one specific network? – sfussenegger Mar 04 '10 at 23:16
  • @sfussenegger a host can have multiple interfaces and each interface can have multiple IPs. It's just typical that a host usually only has a few intefaces (eg eth0, lo) and it's also typical that each interface only has only one IP. Each IP is just as "real" as the next. The only way to figure out which IP you want is to figure out who you want to talk to and look at the routing table. That's why the google.com hack below is almost good, but, since it leaks information (DNS requests and spurious connects) and is just kind of kludgy, I consider it flawed. – jdizzle Mar 05 '10 at 05:09
  • @jdizzle I completely agree. I once made something similar by creating a UDP packat without actually sending it. I think it was C (but might have been Perl), where it was possible to read the source address. Unfortunately, I don't think this is possible in Java though (DatagramPacket doesn't even offer a getSourceAddress() or similar method). I've changed my example to not use DNS though. – sfussenegger Mar 05 '10 at 08:31
  • I understand who's perplex about me giving correct to this answer. This is probably because I was more interested in this call results than the actual method of obtaining the IP (of course I know I have to list the interfaces... but I wanted a quick and dirty way). @Tom Hawtin: Real Ip address may mean many things... I meant the INTERFACE address, someone understood a TRANSLATED address. 192.168.* are REAL IP address but they r reserved for LAN use. RTM. Thanks all and sorry for this rubbish question. – gotch4 Mar 05 '10 at 09:17

10 Answers10

36

If you actually want to work with all of the IP addresses on the machine you can get those with the NetworkInterface class. Of course, then you need to which one you actually want to use, but that's going to be different depending on what you're using it for, or you might need to expand the way you're using it to account for multiple addresses.

import java.net.*;
import java.util.*;

public class ShowInterfaces
{
        public static void main(String[] args) throws Exception
        {
                System.out.println("Host addr: " + InetAddress.getLocalHost().getHostAddress());  // often returns "127.0.0.1"
                Enumeration<NetworkInterface> n = NetworkInterface.getNetworkInterfaces();
                for (; n.hasMoreElements();)
                {
                        NetworkInterface e = n.nextElement();
                        System.out.println("Interface: " + e.getName());
                        Enumeration<InetAddress> a = e.getInetAddresses();
                        for (; a.hasMoreElements();)
                        {
                                InetAddress addr = a.nextElement();
                                System.out.println("  " + addr.getHostAddress());
                        }
                }
        }
}
Eric
  • 5,137
  • 4
  • 34
  • 31
  • 22
    `while (x.hasMoreElements()) {}` would be neater than `for (;x.hasMoreElements();) {}` – sync Nov 25 '12 at 23:49
23

As the machine might have multiple addresses, it's hard to determine which one is the one for you. Normally, you want the system to assign an IP based on its routing table. As the result depends on the IP you'd like to connect to, there is a simple trick: Simply create a connection and see what address you've got from the OS:

// output on my machine: "192.168.1.102"
Socket s = new Socket("192.168.1.1", 80);
System.out.println(s.getLocalAddress().getHostAddress());
s.close();

// output on my machine: "127.0.1.1"
System.out.println(InetAddress.getLocalHost().getHostAddress());

I'm not sure whether it's possible to do this without establishing a connection though. I think I've once managed to do it with Perl (or C?), but don't ask me about Java. I think it might be possible to create a UDP socket (DatagramSocket) without actually connecting it.

If there is a NAT router on the way you won't be able to get the IP that remote hosts will see though. However, as you gave 192.* as an example, I think you don't care.

Adam
  • 15,537
  • 2
  • 42
  • 63
sfussenegger
  • 35,575
  • 15
  • 95
  • 119
  • But how do you know the gateway IP (192.168.1.1) to open the socket to in the first place? – mrod Feb 06 '19 at 07:27
  • @mrod you should use "the IP you'd like to connect to". For instance, you could use `new Socket("www.google.com", 80);` to get the IP address of the interface that routes to the internet – sfussenegger Feb 08 '19 at 15:19
  • right, if we assume the use case is "connecting to another host" this would work :) . If the use case is auditing or any other where there's no connection to another host, I guess there's no 'right' IP address if there are several configured (unless we know of a specific preferred subnetwork, for instance) – mrod Feb 11 '19 at 10:01
  • @mrod I've worked on an auditing project about 12 years ago where I think (as I've mentioned) we've either used Perl or C to create UDP packages without any actual packages being sent and read the source address of the package. And given a machine with multiple network interfaces, the term "real IP" used in the question arguably depends on the destination. Otherwise this approach won't help. – sfussenegger Feb 12 '19 at 11:22
18

To fix it:

  1. Find your host name. Type: hostname. For example, you find your hostname is mycomputer.xzy.com

  2. Put your host name in your hosts file. /etc/hosts . Such as

    10.50.16.136 mycomputer.xzy.com
    
Martijn Courteaux
  • 67,591
  • 47
  • 198
  • 287
boom boom
  • 317
  • 2
  • 5
  • 1
    that's strange way to 'fix' it for me: if your application's host ip change you're dead.. – boly38 Feb 08 '19 at 19:21
11

Here is a way to avoid IPv6 and Loopback results.

public InetAddress getCurrentIp() {
            try {
                Enumeration<NetworkInterface> networkInterfaces = NetworkInterface
                        .getNetworkInterfaces();
                while (networkInterfaces.hasMoreElements()) {
                    NetworkInterface ni = (NetworkInterface) networkInterfaces
                            .nextElement();
                    Enumeration<InetAddress> nias = ni.getInetAddresses();
                    while(nias.hasMoreElements()) {
                        InetAddress ia= (InetAddress) nias.nextElement();
                        if (!ia.isLinkLocalAddress() 
                         && !ia.isLoopbackAddress()
                         && ia instanceof Inet4Address) {
                            return ia;
                        }
                    }
                }
            } catch (SocketException e) {
                LOG.error("unable to get current IP " + e.getMessage(), e);
            }
            return null;
        }
boly38
  • 1,806
  • 24
  • 29
5

I wrote this code:

import java.net.InterfaceAddress;
import java.net.NetworkInterface;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;


private String[] getHostAddresses() {
  Set<String> HostAddresses = new HashSet<>();
  try {
    for (NetworkInterface ni : Collections.list(NetworkInterface.getNetworkInterfaces())) {
      if (!ni.isLoopback() && ni.isUp() && ni.getHardwareAddress() != null) {
        for (InterfaceAddress ia : ni.getInterfaceAddresses()) {
          if (ia.getBroadcast() != null) {  //If limited to IPV4
            HostAddresses.add(ia.getAddress().getHostAddress());
          }
        }
      }
    }
  } catch (SocketException e) { }
  return HostAddresses.toArray(new String[0]);
}

Check it!

For me:

  • Must be not LoopBack!
  • Must be UP!
  • Must have MAC Address (is not null)
joseluisbz
  • 1,491
  • 1
  • 36
  • 58
3

Your computer may have multiple IPs. How do you know which one? The way I do it is to have a very simple CGI running on another machine that reports back the IP it's seen, and I hit that when I need to know what my IP looks like to the outside world.

Paul Tomblin
  • 179,021
  • 58
  • 319
  • 408
2

Instead of using InetAddress.getHostAddress(), I call the getHost4Address routine that I wrote to get the first non-loopback address...

/**
 * Returns this host's non-loopback IPv4 addresses.
 * 
 * @return
 * @throws SocketException 
 */
private static List<Inet4Address> getInet4Addresses() throws SocketException {
    List<Inet4Address> ret = new ArrayList<Inet4Address>();

    Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
    for (NetworkInterface netint : Collections.list(nets)) {
        Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
        for (InetAddress inetAddress : Collections.list(inetAddresses)) {
            if (inetAddress instanceof Inet4Address && !inetAddress.isLoopbackAddress()) {
                ret.add((Inet4Address)inetAddress);
            }
        }
    }

    return ret;
}

/**
 * Returns this host's first non-loopback IPv4 address string in textual
 * representation.
 * 
 * @return
 * @throws SocketException
 */
private static String getHost4Address() throws SocketException {
    List<Inet4Address> inet4 = getInet4Addresses();
    return !inet4.isEmpty()
            ? inet4.get(0).getHostAddress()
            : null;
}
Ken Lin
  • 1,819
  • 21
  • 21
1

Get the current request from the current instance

HttpServletRequest httpServletRequest = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();

then get the address from the request

ip = httpServletRequest.getRemoteAddr();
csharpwinphonexaml
  • 3,659
  • 10
  • 32
  • 63
Eleven
  • 339
  • 2
  • 6
  • 20
1

Get the ip address of the current box matching a pattern:

import java.io.*; 
import java.util.*; 
import java.util.regex.Pattern; 

String ipPattern = "(192.1.200.)(\\d){1,3}";      //your organization pattern 
try{ 
    Enumeration en = NetworkInterface.getNetworkInterfaces(); 
    while (en.hasMoreElements()) { 
        NetworkInterface ni = (NetworkInterface) en.nextElement(); 
        Enumeration ee = ni.getInetAddresses(); 
        while (ee.hasMoreElements()) { 
            InetAddress ia = (InetAddress) ee.nextElement(); 
            String ip = ia.getHostAddress(); 
            System.out.println("ip: '" + ip + "'\n"); 
            boolean matched = Pattern.matches(ipPattern, ip); 
            if (matched) { 
                System.out.println("matched\n"); 
            }
        } 
    } 
} 
catch(Exception e){ } 

Result:

ip: 'fe80:0:0:0:510a:528b:7204:39d0%enp0s25'
ip: '192.1.200.3'
matched
ip: '0:0:0:0:0:0:0:1%lo'
ip: '127.0.0.1'
Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
  • This answer came up for deletion because it was a code-only, I rescued it by adding a title, making the code more self documenting and showing the results. In the future if an answer is code only, without any explanation, then often times it gets autoflagged. – Eric Leschinski Mar 11 '19 at 14:38
  • What if we change the organization? – Mahdi Hesari Dec 06 '19 at 15:17
  • In that regex pattern, the periods are interpreted as "match any character." They need to be escaped to mean a literal period. And the grouping parentheses are technically unnecessary. A more explicit (but uglier) pattern is: "192\\.1\\.200\\.\\d{1,3}" In this particular use-case the original pattern would probably never fail, so no big deal. But if someone unfamiliar with patterns sees this, it might be important to note. – Chris Janicki Jan 24 '23 at 18:36
-6

In case you want to get the IP address of your PC, you have to use the "InetAddress" object, which exists in "java.net.InetAddress" library.

The following method returns your IP:

public String getIp() {

    String myIp = "";
    InetAddress ip;

    try {
        ip = InetAddress.getLocalHost();
        myIp = ip.getHostAddress();      // This method returns the IP.
    } catch (UnknownHostException e) {
        e.printStackTrace();
    }

    return myIp;
}
Origamer7
  • 315
  • 3
  • 17