Получение «внешнего» IP-адреса в Java

84

Я не слишком уверен, как получить внешний IP-адрес машины, как его увидит компьютер за пределами сети.

Мой следующий класс IPAddress получает только локальный IP-адрес машины.

public class IPAddress {

    private InetAddress thisIp;

    private String thisIpAddress;

    private void setIpAdd() {
        try {
            InetAddress thisIp = InetAddress.getLocalHost();
            thisIpAddress = thisIp.getHostAddress().toString();
        } catch (Exception e) {
        }
    }

    protected String getIpAddress() {
        setIpAdd();
        return thisIpAddress;
    }
}
Хулио
источник
13
Вы знаете, что у машины может быть сразу много публичных адресов? Они действительно связаны с сетевым интерфейсом, а не с машиной.
Donal Fellows

Ответы:

169

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

Однако вы можете создать код, который работает на веб-сайте, скажем, в JSP, а затем использовать что-то, что возвращает IP-адрес, откуда пришел запрос:

request.getRemoteAddr()

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

Используйте веб-сервис, например AWS и другие.

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

URL whatismyip = new URL("http://checkip.amazonaws.com");
BufferedReader in = new BufferedReader(new InputStreamReader(
                whatismyip.openStream()));

String ip = in.readLine(); //you get the IP as a String
System.out.println(ip);
Баккал
источник
4
Предупреждение: они
изменили
8
Я бы предложил реализовать по крайней мере два сервера, которые обслуживают ваш IP-адрес, на случай, если один из них в данный момент не работает (конечно, с правильной обработкой ошибок). Я бы выбрал externalip.net (щелкните ссылку «Нужен API?»). Пользуюсь этим сайтом уже больше года, пока у меня не было никаких проблем, и это быстрый сервис, который всегда быстро отвечает.
Замечательная ссылка; Я буду использовать это как часть проверки концепции на сетевом задании университета!
araisbec
Другой альтернативой может быть доступ к веб-серверу или учетной записи хоста, на которой выполняется PHP, просто используйте код @bakkal, указанный выше, и укажите его на свой собственный файл PHP, который просто содержит echo $_SERVER['REMOTE_ADDR'];. Если это единственная или первая строка вывода сценария, все готово.
Kingsolmn
7
Whatsmyip.com, похоже, больше не поддерживает этот тип автоматизации.
Kingsolmn
79

Один из комментариев @stivlo заслуживает ответа:

Вы можете использовать сервис Amazon http://checkip.amazonaws.com

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;

public class IpChecker {

    public static String getIp() throws Exception {
        URL whatismyip = new URL("http://checkip.amazonaws.com");
        BufferedReader in = null;
        try {
            in = new BufferedReader(new InputStreamReader(
                    whatismyip.openStream()));
            String ip = in.readLine();
            return ip;
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
Будет
источник
19

На самом деле «вы не можете» в том смысле, что вы задали вопрос. NAT происходит вне протокола. Ядро вашей машины не может узнать, как ваш блок NAT отображает внешние IP-адреса на внутренние. Другие ответы здесь предлагают уловки, связанные с методами общения с внешними веб-сайтами.

bmargulies
источник
3
Или нет, поскольку он не отвечает на исходный вопрос и выглядит как академическое упражнение
Бруно Босола
Честно говоря, этот ответ действительно отвечает на вопрос, а остальные дюжины ответов в основном говорят об одном и том же, но показывают код или URL-адреса, специфичные для любого выбранного внешнего средства проверки IP.
Thomas Carlisle
14

Все это до сих пор работает и работает без сбоев! (по состоянию на 23 сентября 2019 г.)

Совет: не полагайтесь напрямую только на одного из них; попробуйте использовать один, но имейте план действий на случай непредвиденных обстоятельств, учитывая другие! Чем больше вы используете, тем лучше!

Удачи!

Франсиско Буза
источник
12

Как писал @Donal Fellows, вы должны запрашивать сетевой интерфейс, а не машину. Этот код из javadocs работал у меня:

В следующем примере программы перечислены все сетевые интерфейсы и их адреса на машине:

import java.io.*;
import java.net.*;
import java.util.*;
import static java.lang.System.out;

public class ListNets {

    public static void main(String args[]) throws SocketException {
        Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
        for (NetworkInterface netint : Collections.list(nets))
            displayInterfaceInformation(netint);
    }

    static void displayInterfaceInformation(NetworkInterface netint) throws SocketException {
        out.printf("Display name: %s\n", netint.getDisplayName());
        out.printf("Name: %s\n", netint.getName());
        Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
        for (InetAddress inetAddress : Collections.list(inetAddresses)) {
            out.printf("InetAddress: %s\n", inetAddress);
        }
        out.printf("\n");
     }
} 

Ниже приводится пример вывода из примера программы:

Display name: TCP Loopback interface
Name: lo
InetAddress: /127.0.0.1

Display name: Wireless Network Connection
Name: eth0
InetAddress: /192.0.2.0

С сайта docs.oracle.com

домих
источник
1
Благодарю вас! Хотя это решение не будет работать, когда программное обеспечение находится за NAT, оно по-прежнему очень полезно для серверного программного обеспечения, которое, как вы знаете, не будет за NAT, или в качестве запасного варианта, если программное обеспечение не может подключиться к другому серверу, чтобы получить его. IP. В частности, для программного обеспечения, предназначенного для работы в локальных сетях, отключенных от Интернета, это правильный путь.
pavon
6

Сделайте HttpURLConnection к какому-нибудь сайту, например www.whatismyip.com, и проанализируйте его :-)

nc3b
источник
5

Как насчет этого? Это просто и сработало лучше всего :)

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;


public class IP {
    public static void main(String args[]) {
        new IP();
    }

    public IP() {
        URL ipAdress;

        try {
            ipAdress = new URL("http://myexternalip.com/raw");

            BufferedReader in = new BufferedReader(new InputStreamReader(ipAdress.openStream()));

            String ip = in.readLine();
            System.out.println(ip);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
Sparkoenig
источник
Это отлично! Я попробую, когда вернусь домой. Это именно то решение проблемы, которое я искал. Не знаю, почему за него не проголосовали выше.
Adam893,
4

http://jstun.javawi.de/ сделает это - при условии, что ваше устройство шлюза выполняет STUN) в большинстве случаев)

user461467
источник
1
Довольно интересно, он работает, как ожидалось, без использования внешних служб, а просто разговаривает со шлюзом. Однако лицензия GPL, вероятно, ограничит ее принятие.
Бруно Босола,
Сайт дает мне экран входа в систему. Наверное, не оригинал.
Jus12
1

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

Я бы посоветовал вам воспользоваться этим, открыв такой сайт, как http://www.whatismyip.com/ и получив IP-адрес путем анализа результатов html ... это не должно быть так сложно!

Джек
источник
2
Вам не нужно разбирать html. Первая строка источника веб-страницы whatismyip.com - это ваш внешний IP-адрес.
Martijn Courteaux
0

Если вы используете веб-приложение на основе JAVA и хотите получить внешний IP-адрес клиента (того, кто делает запрос через браузер), попробуйте развернуть приложение в общедоступном домене и использовать request.getRemoteAddr () для чтения внешнего IP-адреса.

Джей
источник
0
System.out.println(pageCrawling.getHtmlFromURL("http://ipecho.net/plain"));
Мохсен Абаси
источник
0

Альтернативное решение - выполнить внешнюю команду, очевидно, это решение ограничивает переносимость приложения.

Например, для приложения, работающего в Windows, команда PowerShell может выполняться через jPowershell, как показано в следующем коде:

public String getMyPublicIp() {
    // PowerShell command
    String command = "(Invoke-WebRequest ifconfig.me/ip).Content.Trim()";
    String powerShellOut = PowerShell.executeSingleCommand(command).getCommandOutput();

    // Connection failed
    if (powerShellOut.contains("InvalidOperation")) {
        powerShellOut = null;
    }
    return powerShellOut;
}
Карлос Альма
источник