无需连接到互联网即可获取本地 IP 地址

Posted

技术标签:

【中文标题】无需连接到互联网即可获取本地 IP 地址【英文标题】:Get local IP-Address without connecting to the internet 【发布时间】:2012-02-04 15:20:56 【问题描述】:

所以,我正在尝试在本地网络中获取我的机器的 IP 地址(应该是 192.168.178.41)。

我的第一个意图是使用这样的东西:

InetAddress.getLocalHost().getHostAddress();

但它只返回127.0.0.1,这是正确的,但对我帮助不大。

我四处搜索并找到了这个答案https://***.com/a/2381398/717341,它只是创建了一个Socket-连接到某个网页(例如“google.com”)并从套接字获取本地主机地址:

Socket s = new Socket("google.com", 80);
System.out.println(s.getLocalAddress().getHostAddress());
s.close();

这确实适用于我的机器(它返回192.168.178.41),但它需要连接到互联网才能工作。由于我的应用程序不需要互联网连接,而且每次启动时应用程序都会尝试连接到 google 看起来“可疑”,所以我不喜欢使用它。

所以,经过更多研究后,我偶然发现了NetworkInterface-class,它(通过一些工作)也确实返回了所需的 IP 地址:

Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements())
    NetworkInterface current = interfaces.nextElement();
    System.out.println(current);
    if (!current.isUp() || current.isLoopback() || current.isVirtual()) continue;
    Enumeration<InetAddress> addresses = current.getInetAddresses();
    while (addresses.hasMoreElements())
        InetAddress current_addr = addresses.nextElement();
        if (current_addr.isLoopbackAddress()) continue;
        System.out.println(current_addr.getHostAddress());
    

在我的机器上,这会返回以下内容:

name:eth1 (eth1)
fe80:0:0:0:226:4aff:fe0d:592e%3
192.168.178.41
name:lo (lo)

它会找到我的网络接口并返回所需的 IP,但我不确定其他地址 (fe80:0:0:0:226:4aff:fe0d:592e%3) 的含义。

此外,我还没有找到一种方法从返回的地址中过滤它(通过使用InetAddress-object 的isXX()-方法),然后使用 RegEx,我发现它非常“脏”。

除了使用 RegEx 或互联网之外,还有其他想法吗?

【问题讨论】:

fe80:0:0:0:226:4aff:fe0d:592e 看起来像 IPv6 地址 fe80::... 是 IPv6 链路本地地址 顺便问一下,你想“过滤”什么?当然,您知道机器可以是多宿主的吗? 【参考方案1】:

fe80:0:0:0:226:4aff:fe0d:592e 是您的 ipv6 地址 ;-)。

检查这个使用

if (current_addr instanceof Inet4Address)
  System.out.println(current_addr.getHostAddress());
else if (current_addr instanceof Inet6Address)
  System.out.println(current_addr.getHostAddress());

如果您只关心 IPv4,那么只需放弃 IPv6 的情况。但请注意,IPv6 是未来 ^^.

P.S.:检查您的某些 breaks 是否应该是 continues。

【讨论】:

getHostAddress() 存在于 InetAddress 基类中,这里不需要强制转换 (docs.oracle.com/javase/6/docs/api/java/net/…) 这看起来很不错,而且很有效。虽然只是为了过滤它们,但您不需要演员表。我知道 IPv6 是未来,但就我目前的需求而言,IPv4 就可以了;-) 当然,您对breaks 的看法是正确的。我纠正了这一点。谢谢直到这里! @yankee:我认为没有采取观点:if 也没有必要。 @skaffmann:确实,if 在这个例子中毫无意义,但为了解释如何区分 IPv4 和 IPv6,我不会改变它。毕竟问题似乎也只是提取 IPv4 地址 免责声明:这不包括绑定到不同地址的多个网络接口。它只会检索一个而忽略所有其他的。【参考方案2】:

这也是java 8的一种做法:

public static String getIp() throws SocketException 

    return Collections.list(NetworkInterface.getNetworkInterfaces()).stream()
            .flatMap(i -> Collections.list(i.getInetAddresses()).stream())
            .filter(ip -> ip instanceof Inet4Address && ip.isSiteLocalAddress())
            .findFirst().orElseThrow(RuntimeException::new)
            .getHostAddress();

【讨论】:

这是返回我的实际 LAN IP 地址的唯一解决方案。谢谢!【参考方案3】:
public static String getIp()
    String ipAddress = null;
    Enumeration<NetworkInterface> net = null;
    try 
        net = NetworkInterface.getNetworkInterfaces();
     catch (SocketException e) 
        throw new RuntimeException(e);
    

    while(net.hasMoreElements())
        NetworkInterface element = net.nextElement();
        Enumeration<InetAddress> addresses = element.getInetAddresses();
        while (addresses.hasMoreElements())
            InetAddress ip = addresses.nextElement();
            if (ip instanceof Inet4Address)

                if (ip.isSiteLocalAddress())

                    ipAddress = ip.getHostAddress();
                

            

        
    
    return ipAddress;

【讨论】:

这与我提供的答案和答案有何不同? 返回“192.168.56.1”但我的局域网地址是“10.0.0.5”【参考方案4】:
import java.net.*;

public class Get_IP

    public static void main(String args[])
    
        try
        
            InetAddress addr = InetAddress.getLocalHost();
            String hostname = addr.getHostName();
            System.out.println(addr.getHostAddress());
            System.out.println(hostname);
        catch(UnknownHostException e)
        
             //throw Exception
        


    

【讨论】:

正如我上面提到的,这在 Linux 上为您提供127.0.0.1。但是,这可能适用于 Windows 系统... 一开始就提到了。【参考方案5】:

洋基对第一部分的回答是正确的。要打印出 IP 地址,您可以将其作为字节数组获取并将其转换为正常的字符串表示形式,如下所示:

StringBuilder ip = new StringBuilder();
for(byte b : current_addr.getAddress()) 
    // The & here makes b convert like an unsigned byte - so, 255 instead of -1.
    ip.append(b & 0xFF).append('.');

ip.setLength(ip.length() - 1); // To remove the last '.'
System.out.println(ip.toString());

【讨论】:

与仅使用 current_addr.getHostAddress() 相比有什么优势? @Lukas Knuth:起初我的回答中没有指纹。一分钟后,我将它们编辑到帖子中,因为我认为这可能会很有帮助;-)。拉塞尔可能没有看到那个版本。 哎呀,我的错 - 我认为 getHostAddress 正在打印出 yankee 必须正则表达式的全文。我没有注意到 current 的早期版本。

以上是关于无需连接到互联网即可获取本地 IP 地址的主要内容,如果未能解决你的问题,请参考以下文章

设备在Android中连接到WiFi时如何获取蜂窝网络的IP地址

Ubuntu查不到eth 0的IP地址了

使用带有OPEN CV的IP摄像头,无需互联网连接(直接连接到PC)

通过 MYSQL 工作台连接到 RDS 实例,无需静态 IP

C# - 连接到 (RAS) *** 时如何获取 IP 地址

连接到公共 IP 地址的 Java 套接字