Pobieranie „zewnętrznego” adresu IP w Javie

84

Nie jestem pewien, jak uzyskać zewnętrzny adres IP urządzenia, ponieważ komputer spoza sieci może go zobaczyć.

Moja następująca klasa IPAddress pobiera tylko lokalny adres IP urządzenia.

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;
    }
}
Julio
źródło
14
Wiesz, że maszyna może mieć jednocześnie wiele adresów publicznych? Są tak naprawdę związane z interfejsem sieciowym, a nie maszyną.
Donal Fellows

Odpowiedzi:

169

Nie jestem pewien, czy możesz pobrać ten adres IP z kodu działającego na komputerze lokalnym.

Możesz jednak zbudować kod działający na stronie internetowej, na przykład w JSP, a następnie użyć czegoś, co zwraca adres IP, z którego pochodzi żądanie:

request.getRemoteAddr()

Lub po prostu użyj już istniejących usług, które to robią, a następnie przeanalizuj odpowiedź z usługi, aby znaleźć adres IP.

Korzystaj z usług sieciowych, takich jak AWS i inne

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);
bakkal
źródło
4
Słowo ostrzeżenia: dostosowali adres URL automatyzacji
thegrinner
8
Sugerowałbym zaimplementowanie co najmniej dwóch serwerów obsługujących Twój adres IP na wypadek, gdyby jeden z nich był w tej chwili wyłączony (z poprawną obsługą błędów). Mój wybór to externalip.net (kliknij łącze „Potrzebujesz interfejsu API?”). Korzystam z tej witryny od ponad roku, do tej pory nie miałem żadnych problemów i jest to szybka usługa, która zawsze zwraca szybką odpowiedź.
Niesamowity link; Będę używał tego jako części dowodu słuszności przy zadaniu sieciowym na uniwersytecie!
araisbec
Inną alternatywą byłoby, gdybyś miał dostęp do serwera WWW lub konta hosta, na którym działa PHP, po prostu użyj kodu @bakkal podanego powyżej i wskaż swój własny plik PHP, który po prostu zawiera echo $_SERVER['REMOTE_ADDR'];. Jeśli jest to jedyny lub pierwszy wiersz wyjściowy skryptu, wszystko jest ustawione.
Kingsolmn
7
Wygląda na to, że Whatsmyip.com nie obsługuje już tego typu automatyzacji.
Kingsolmn
79

Na odpowiedź zasługuje jeden z komentarzy @stivlo:

Możesz skorzystać z usługi 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();
                }
            }
        }
    }
}
Wola
źródło
19

Prawda jest taka: „nie możesz” w tym sensie, w jakim zadałeś pytanie. NAT odbywa się poza protokołem. Jądro twojej maszyny nie ma możliwości dowiedzenia się, w jaki sposób twój NAT mapuje z zewnętrznych na wewnętrzne adresy IP. Inne odpowiedzi oferują sztuczki związane z metodami rozmawiania z zewnętrznymi witrynami internetowymi.

bmargulies
źródło
3
Albo nie, bo nie odpowiada na pierwotne pytanie, a wygląda na ćwiczenie akademickie
Bruno Bossola
Szczerze mówiąc, ta odpowiedź odpowiada na pytanie, a pozostałe tuziny odpowiedzi zasadniczo mówią to samo, ale pokazują kod lub adresy URL specyficzne dla dowolnego wybranego zewnętrznego narzędzia do sprawdzania adresów IP.
Thomas Carlisle
14

Wszystko to nadal działa i działa płynnie! (stan na 23 września 2019 r.)

Rada: nie polegaj bezpośrednio tylko na jednym z nich; spróbuj użyć jednego, ale miej plan awaryjny z uwzględnieniem innych! Im więcej używasz, tym lepiej!

Powodzenia!

FranciscoBouza
źródło
12

Jak napisał @Donal Fellows, musisz zapytać interfejs sieciowy zamiast maszyny. Ten kod z javadocs zadziałał dla mnie:

Poniższy przykładowy program zawiera listę wszystkich interfejsów sieciowych i ich adresów na komputerze:

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

Poniżej przedstawiono przykładowe dane wyjściowe z przykładowego programu:

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

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

Z docs.oracle.com

domih
źródło
1
Dziękuję Ci! Chociaż to rozwiązanie nie będzie działać, gdy oprogramowanie jest za NAT, nadal jest bardzo pomocne w przypadku oprogramowania serwera, o którym wiesz, że nie będzie za NAT, lub jako rozwiązanie zastępcze, jeśli oprogramowanie nie może połączyć się z innym serwerem, aby uzyskać własny IP. W szczególności w przypadku oprogramowania przeznaczonego do uruchamiania w sieciach LAN odłączonych od Internetu jest to droga do zrobienia.
pavon
6

Utwórz połączenie HttpURLConnection z jakąś witryną, taką jak www.whatismyip.com, i przeanalizuj to :-)

nc3b
źródło
5

Co powiesz na to? To proste i działało najlepiej dla mnie :)

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
źródło
To jest doskonałe! Spróbuję, kiedy wrócę do domu. To jest dokładnie taki sposób rozwiązywania problemów, jakiego szukałem. Nie wiem, dlaczego nie został oceniony wyżej.
Adam893,
4

http://jstun.javawi.de/ zrobi to - pod warunkiem, że Twoje urządzenie bramy STUN))

user461467
źródło
1
Dość interesujące, działa zgodnie z oczekiwaniami bez korzystania z usług zewnętrznych, ale po prostu rozmawia z bramą. Jednak licencja GPL prawdopodobnie ograniczy jej przyjęcie.
Bruno Bossola
Witryna wyświetla ekran logowania. Prawdopodobnie nie oryginał.
Jus
1

Nie jest to takie proste, ponieważ maszyna w sieci LAN zwykle nie dba o zewnętrzny adres IP swojego routera do Internetu… po prostu go nie potrzebuje!

Sugeruję, abyś to wykorzystał, otwierając witrynę taką jak http://www.whatismyip.com/ i uzyskując numer IP, analizując wyniki HTML .. nie powinno być takie trudne!

Jacek
źródło
2
Nie musisz analizować html. Pierwsza linia źródła strony internetowej whatismyip.com to Twój zewnętrzny adres IP.
Martijn Courteaux
0

Jeśli używasz aplikacji internetowej opartej na JAVA i chcesz pobrać zewnętrzny adres IP klienta (tego, który wysyła żądanie przez przeglądarkę), spróbuj wdrożyć aplikację w domenie publicznej i użyj request.getRemoteAddr () do odczytania zewnętrznego adresu IP.

Sójka
źródło
0
System.out.println(pageCrawling.getHtmlFromURL("http://ipecho.net/plain"));
Mohsen Abasi
źródło
0

Alternatywnym rozwiązaniem jest wykonanie zewnętrznego polecenia, oczywiście takie rozwiązanie ogranicza przenośność aplikacji.

Na przykład w przypadku aplikacji działającej w systemie Windows polecenie PowerShell można wykonać za pomocą jPowershell, jak pokazano w poniższym kodzie:

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;
}
Carlos Alma
źródło