Получение IP-адреса текущего компьютера с использованием Java - PullRequest
264 голосов
/ 28 февраля 2012

Я пытаюсь разработать систему, в которой есть разные узлы, которые работают на разных системах или на разных портах в одной и той же системе.

Теперь все узлы создают Socket с целевым IP-адресом в качестве IP-адреса специального узла, известного как узел начальной загрузки. Затем узлы создают свои собственные ServerSocket и начинают прослушивать соединения.

Узел начальной загрузки поддерживает список узлов и возвращает их при запросе.

Теперь мне нужно, чтобы узел зарегистрировал свой IP на узле начальной загрузки. Я попытался использовать cli.getInetAddress() после подключения клиента к ServerSocket узла начальной загрузки, но это не сработало.

  1. Мне нужно, чтобы клиент зарегистрировал свой PPP IP, если он доступен;
  2. В противном случае IP-адрес ЛВС, если имеется
  3. В противном случае он должен зарегистрировать 127.0.0.1, предполагая, что это тот же компьютер.

Используя код:

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

или

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

Мой IP-адрес соединения PPP: 117.204.44.192, но приведенное выше возвращает меня 192.168.1.2

EDIT

Я использую следующий код:

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

Я могу получить все IP-адреса, связанные со всеми NetworkInterface с, но как их различить? Это вывод, который я получаю:

127.0.0.1
192.168.1.2
192.168.56.1
117.204.44.19

Ответы [ 17 ]

258 голосов
/ 28 февраля 2012

Это может быть немного сложно в самом общем случае.

На первый взгляд, InetAddress.getLocalHost() должен дать вам IP-адрес этого хоста.Проблема в том, что хост может иметь множество сетевых интерфейсов, и интерфейс может быть связан с несколькими IP-адресами.Кроме того, не все IP-адреса будут доступны за пределами вашей машины или локальной сети.Например, это могут быть IP-адреса для виртуальных сетевых устройств, IP-адреса частных сетей и т. Д.

Это означает, что IP-адрес, возвращаемый InetAddress.getLocalHost(), может быть неправильным для использования.

Как вы можете справиться с этим?

  • Один из подходов заключается в использовании NetworkInterface.getNetworkInterfaces() для получения всех известных сетевых интерфейсов на хосте, а затем итерации по адресам каждого NI.
  • Другой подход состоит в том, чтобы (каким-то образом) получить внешнее полное доменное имя для хоста и использовать InetAddress.getByName() для поиска первичного IP-адреса.(Но как его получить и как вы работаете с балансировщиком нагрузки на основе DNS?)
  • Разновидностью предыдущего является получение предпочтительного полного доменного имени из файла конфигурации или параметра командной строки.
  • Другим вариантом является получение предпочтительного IP-адреса из файла конфигурации или параметра командной строки.

В итоге, InetAddress.getLocalHost() обычно будет работать, но вам может потребоваться предоставитьальтернативный метод для случаев, когда ваш код выполняется в среде со «сложной» сетью.


Я могу получить все IP-адреса, связанные со всеми сетевыми интерфейсами, но как мне отличитьих?

  • Любой адрес в диапазоне 127.xxx.xxx.xxx является адресом обратной связи.Он виден только «этому» хосту.
  • Любой адрес в диапазоне 192.168.xxx.xxx является частным (он же локальный IP-адрес сайта).Они зарезервированы для использования в организации.То же самое относится к адресам 10.xxx.xxx.xxx и 172.16.xxx.xxx - 172.31.xxx.xxx.
  • Адреса в диапазоне 169.254.xxx.xxx являются локальными IP-адресами связи.Они зарезервированы для использования в одном сегменте сети.
  • Адреса в диапазоне от 224.xxx.xxx.xxx до 239.xxx.xxx.xxx являются многоадресными адресами.
  • Адрес 255.255.255.255 - это широковещательный адрес.
  • Все остальное должно быть действительным общедоступным двухточечным IPv4-адресом.

На самом деле API InetAddress предоставляет методыдля проверки петлевых, локальных, локальных, многоадресных и широковещательных адресов.Вы можете использовать их, чтобы выбрать наиболее подходящий IP-адрес.

88 голосов
/ 13 июля 2016
import java.net.DatagramSocket;

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

Этот способ хорошо работает при наличии нескольких сетевых интерфейсов.Всегда возвращает предпочитаемый исходящий IP-адрес.Пункт назначения 8.8.8.8 не требуется, чтобы быть достижимым.

Connect на сокете UDP имеет следующий эффект: он устанавливает пункт назначения для отправки / записи, отбрасывает все пакеты с других адресов и - что мы используем - переводит сокет в состояние «подключено»Настройте соответствующие поля.Это включает в себя проверку наличия маршрута к пункту назначения в соответствии с таблицей маршрутизации системы и соответствующей настройкой локальной конечной точки.Последняя часть, кажется, официально не документирована, но выглядит как неотъемлемая черта API сокетов Berkeley (побочный эффект состояния UDP «подключен»), который надежно работает как в Windows, так и в Linux в разных версиях и дистрибутивах.

Итак, этот метод даст локальный адрес, который будет использоваться для подключения к указанному удаленному хосту.Реальное соединение не установлено, поэтому указанный удаленный IP-адрес может быть недоступен.

53 голосов
/ 06 декабря 2013

Размещение здесь проверенного кода обхода неоднозначности IP от https://issues.apache.org/jira/browse/JCS-40 (неоднозначность InetAddress.getLocalHost () в системах Linux):

/**
 * Returns an <code>InetAddress</code> object encapsulating what is most likely the machine's LAN IP address.
 * <p/>
 * This method is intended for use as a replacement of JDK method <code>InetAddress.getLocalHost</code>, because
 * that method is ambiguous on Linux systems. Linux systems enumerate the loopback network interface the same
 * way as regular LAN network interfaces, but the JDK <code>InetAddress.getLocalHost</code> method does not
 * specify the algorithm used to select the address returned under such circumstances, and will often return the
 * loopback address, which is not valid for network communication. Details
 * <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4665037">here</a>.
 * <p/>
 * This method will scan all IP addresses on all network interfaces on the host machine to determine the IP address
 * most likely to be the machine's LAN address. If the machine has multiple IP addresses, this method will prefer
 * a site-local IP address (e.g. 192.168.x.x or 10.10.x.x, usually IPv4) if the machine has one (and will return the
 * first site-local address if the machine has more than one), but if the machine does not hold a site-local
 * address, this method will return simply the first non-loopback address found (IPv4 or IPv6).
 * <p/>
 * If this method cannot find a non-loopback address using this selection algorithm, it will fall back to
 * calling and returning the result of JDK method <code>InetAddress.getLocalHost</code>.
 * <p/>
 *
 * @throws UnknownHostException If the LAN address of the machine cannot be found.
 */
private static InetAddress getLocalHostLANAddress() throws UnknownHostException {
    try {
        InetAddress candidateAddress = null;
        // Iterate all NICs (network interface cards)...
        for (Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); ifaces.hasMoreElements();) {
            NetworkInterface iface = (NetworkInterface) ifaces.nextElement();
            // Iterate all IP addresses assigned to each card...
            for (Enumeration inetAddrs = iface.getInetAddresses(); inetAddrs.hasMoreElements();) {
                InetAddress inetAddr = (InetAddress) inetAddrs.nextElement();
                if (!inetAddr.isLoopbackAddress()) {

                    if (inetAddr.isSiteLocalAddress()) {
                        // Found non-loopback site-local address. Return it immediately...
                        return inetAddr;
                    }
                    else if (candidateAddress == null) {
                        // Found non-loopback address, but not necessarily site-local.
                        // Store it as a candidate to be returned if site-local address is not subsequently found...
                        candidateAddress = inetAddr;
                        // Note that we don't repeatedly assign non-loopback non-site-local addresses as candidates,
                        // only the first. For subsequent iterations, candidate will be non-null.
                    }
                }
            }
        }
        if (candidateAddress != null) {
            // We did not find a site-local address, but we found some other non-loopback address.
            // Server might have a non-site-local address assigned to its NIC (or it might be running
            // IPv6 which deprecates the "site-local" concept).
            // Return this non-loopback candidate address...
            return candidateAddress;
        }
        // At this point, we did not find a non-loopback address.
        // Fall back to returning whatever InetAddress.getLocalHost() returns...
        InetAddress jdkSuppliedAddress = InetAddress.getLocalHost();
        if (jdkSuppliedAddress == null) {
            throw new UnknownHostException("The JDK InetAddress.getLocalHost() method unexpectedly returned null.");
        }
        return jdkSuppliedAddress;
    }
    catch (Exception e) {
        UnknownHostException unknownHostException = new UnknownHostException("Failed to determine LAN address: " + e);
        unknownHostException.initCause(e);
        throw unknownHostException;
    }
}
48 голосов
/ 28 февраля 2012

Вы можете использовать Java InetAddress класс для этой цели.

InetAddress IP=InetAddress.getLocalHost();
System.out.println("IP of my system is := "+IP.getHostAddress());

Выход для моей системы = IP of my system is := 10.100.98.228

getHostAddress () возвращает

Возвращает строку IP-адреса в текстовом представлении.

ИЛИ вы также можете сделать

InetAddress IP=InetAddress.getLocalHost();
System.out.println(IP.toString());

Выход = IP of my system is := RanRag-PC/10.100.98.228

14 голосов
/ 24 января 2017

Когда вы ищете свой «локальный» адрес, вы должны заметить, что у каждой машины есть не только один сетевой интерфейс, и у каждого интерфейса может быть свой собственный локальный адрес. Это означает, что ваша машина всегда владеет несколькими «локальными» адресами.

Различные «локальные» адреса будут автоматически выбраны для использования при подключении к различным конечным точкам. Например, когда вы подключаетесь к google.com, вы используете «внешний» локальный адрес; но когда вы подключаетесь к своему localhost, ваш локальный адрес всегда сам по себе localhost, потому что localhost - это просто петля.

Ниже показано, как узнать ваш локальный адрес, когда вы общаетесь с google.com:

Socket socket = new Socket();
socket.connect(new InetSocketAddress("google.com", 80));
System.out.println(socket.getLocalAddress());
10 голосов
/ 09 июля 2014

Пример в scala (полезно в файле sbt):

  import collection.JavaConverters._
  import java.net._

  def getIpAddress: String = {

    val enumeration = NetworkInterface.getNetworkInterfaces.asScala.toSeq

    val ipAddresses = enumeration.flatMap(p =>
      p.getInetAddresses.asScala.toSeq
    )

    val address = ipAddresses.find { address =>
      val host = address.getHostAddress
      host.contains(".") && !address.isLoopbackAddress
    }.getOrElse(InetAddress.getLocalHost)

    address.getHostAddress
  }
9 голосов
/ 28 февраля 2012

РЕДАКТИРОВАТЬ 1: обновленный код, поскольку предыдущая ссылка больше не существует

import java.io.*;
import java.net.*;

public class GetMyIP {
    public static void main(String[] args) {
        URL url = null;
        BufferedReader in = null;
        String ipAddress = "";
        try {
            url = new URL("http://bot.whatismyipaddress.com");
            in = new BufferedReader(new InputStreamReader(url.openStream()));
            ipAddress = in.readLine().trim();
            /* IF not connected to internet, then
             * the above code will return one empty
             * String, we can check it's length and
             * if length is not greater than zero, 
             * then we can go for LAN IP or Local IP
             * or PRIVATE IP
             */
            if (!(ipAddress.length() > 0)) {
                try {
                    InetAddress ip = InetAddress.getLocalHost();
                    System.out.println((ip.getHostAddress()).trim());
                    ipAddress = (ip.getHostAddress()).trim();
                } catch(Exception exp) {
                    ipAddress = "ERROR";
                }
            }
        } catch (Exception ex) {
            // This try will give the Private IP of the Host.
            try {
                InetAddress ip = InetAddress.getLocalHost();
                System.out.println((ip.getHostAddress()).trim());
                ipAddress = (ip.getHostAddress()).trim();
            } catch(Exception exp) {
                ipAddress = "ERROR";
            }
            //ex.printStackTrace();
        }
        System.out.println("IP Address: " + ipAddress);
    }
}

АКТУАЛЬНАЯ ВЕРСИЯ: Это перестало работать

Надеюсь, этот фрагмент поможет вам достичь этого:

// Method to get the IP Address of the Host.
private String getIP()
{
    // This try will give the Public IP Address of the Host.
    try
    {
        URL url = new URL("http://automation.whatismyip.com/n09230945.asp");
        BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
        String ipAddress = new String();
        ipAddress = (in.readLine()).trim();
        /* IF not connected to internet, then
         * the above code will return one empty
         * String, we can check it's length and
         * if length is not greater than zero, 
         * then we can go for LAN IP or Local IP
         * or PRIVATE IP
         */
        if (!(ipAddress.length() > 0))
        {
            try
            {
                InetAddress ip = InetAddress.getLocalHost();
                System.out.println((ip.getHostAddress()).trim());
                return ((ip.getHostAddress()).trim());
            }
            catch(Exception ex)
            {
                return "ERROR";
            }
        }
        System.out.println("IP Address is : " + ipAddress);

        return (ipAddress);
    }
    catch(Exception e)
    {
        // This try will give the Private IP of the Host.
        try
        {
            InetAddress ip = InetAddress.getLocalHost();
            System.out.println((ip.getHostAddress()).trim());
            return ((ip.getHostAddress()).trim());
        }
        catch(Exception ex)
        {
            return "ERROR";
        }
    }
}
6 голосов
/ 12 августа 2014

сначала импортируйте класс

import java.net.InetAddress;

в классе

  InetAddress iAddress = InetAddress.getLocalHost();
  String currentIp = iAddress.getHostAddress();
  System.out.println("Current IP address : " +currentIp); //gives only host address
5 голосов
/ 03 ноября 2014
private static InetAddress getLocalAddress(){
        try {
            Enumeration<NetworkInterface> b = NetworkInterface.getNetworkInterfaces();
            while( b.hasMoreElements()){
                for ( InterfaceAddress f : b.nextElement().getInterfaceAddresses())
                    if ( f.getAddress().isSiteLocalAddress())
                        return f.getAddress();
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return null;
    }
5 голосов
/ 28 февраля 2012

Вы можете использовать java.net.InetAddress API.Попробуйте это:

InetAddress.getLocalHost().getHostAddress();
...