Lấy địa chỉ IP 'bên ngoài' trong Java


83

Tôi không chắc về cách lấy địa chỉ IP bên ngoài của máy vì máy tính bên ngoài mạng sẽ nhìn thấy nó.

Lớp IPAddress sau của tôi chỉ lấy địa chỉ IP cục bộ của máy.

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
You are aware that a machine can have many public addresses at once? They're really associated with a network interface, not a machine.
Donal Fellows

Câu trả lời:


168

I am not sure if you can grab that IP from code that runs on the local machine.

You can however build code that runs on a website, say in JSP, and then use something that returns the IP of where the request came from:

request.getRemoteAddr()

Or simply use already-existing services that do this, then parse the answer from the service to find out the IP.

Use a webservice like AWS and others

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
Word of warning: they've adjusted the automation URL to automation.whatismyip.com/n09230945.asp
thegrinner

8
I would suggest implementing at least two servers that serves your ip, in case one of them is down at the moment (with correct error handling of course). My choise would be externalip.net (click the "Need an API?" link). Have been using that site for well over a year now, haven't had any problems so far and it's a fast service that always returns a quick response.

Awesome link; I will be using this as part of a proof of concept on a University networking assignment!
araisbec

Another alternative would be if you have access to a web server or host account that runs PHP simply use the code @bakkal provided above and point it to your own PHP file that simply contains echo $_SERVER['REMOTE_ADDR'];. If this is the only or first output line of the script you're all set.
Kingsolmn

7
Whatsmyip.com does not appear to support this type of automation any more.
Kingsolmn

79

One of the comments by @stivlo deserves to be an answer:

You can use the Amazon service 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

The truth is: 'you can't' in the sense that you posed the question. NAT happens outside of the protocol. There is no way for your machine's kernel to know how your NAT box is mapping from external to internal IP addresses. Other answers here offer tricks involving methods of talking to outside web sites.


3
Or not, as it does not answer the original question, and it looks like an academic exercise
Bruno Bossola

To be fair, this answer does answer the question and the other dozen answers all basically say the same thing but show code or URLs specific to any given choice of external ip checker.
Thomas Carlisle

14

All this are still up and working smoothly! (as of 23 Sep 2019)

Piece of advice: Do not direcly depend only on one of them; try to use one but have a contigency plan considering others! The more you use, the better!

Good luck!


12

As @Donal Fellows wrote, you have to query the network interface instead of the machine. This code from the javadocs worked for me:

The following example program lists all the network interfaces and their addresses on a machine:

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

The following is sample output from the example program:

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

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

From docs.oracle.com


1
Thank You! While this solution won't work when the software is behind a NAT, it is still very helpful for server software that you know won't be behind a NAT, or as a fallback if the software cannot connect to another server to get it's own IP. In particular for software intended to be run on LANs disconnected from the internet, it is the way to go.
pavon

6

Make a HttpURLConnection to some site like www.whatismyip.com and parse that :-)


5

How about this? It's simple and worked the best for me :)

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

This is excellent! I will try it when i get home. This is exactly the kind of problem solving i was looking for. Don't know why it hasn't been voted higher.
Adam893

4

http://jstun.javawi.de/ will do it - provided your gateway device does STUN )most do)


1
Quite interesting, it works as expected without the use of external services but simply talking to the gateway. The GPL license however will probably limit its adoption.
Bruno Bossola

Site is giving me a login screen. Probably not the original.
Jus12

1

It's not that easy since a machine inside a LAN usually doesn't care about the external IP of its router to the internet.. it simply doesn't need it!

I would suggest you to exploit this by opening a site like http://www.whatismyip.com/ and getting the IP number by parsing the html results.. it shouldn't be that hard!


2
You don't have to parse html. The first line of the webpage source of whatismyip.com is your external IP.
Martijn Courteaux

0

If you are using JAVA based webapp and if you want to grab the client's (One who makes the request via a browser) external ip try deploying the app in a public domain and use request.getRemoteAddr() to read the external IP address.



0

An alternative solution is to execute an external command, obviously, this solution limits the portability of the application.

For example, for an application that runs on Windows, a PowerShell command can be executed through jPowershell, as shown in the following code:

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;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.