如何在 Java 中确定我的路由器/网关的 IP?

Posted

技术标签:

【中文标题】如何在 Java 中确定我的路由器/网关的 IP?【英文标题】:How can I determine the IP of my router/gateway in Java? 【发布时间】:2010-09-05 22:20:51 【问题描述】:

我可以很容易地获得我的IP。我可以使用网站上的服务获取我的互联网 IP。但是如何确定网关的 IP?

如果您知道自己的方式,这在 .NET 中有点容易。但是你如何在 Java 中做到这一点?

【问题讨论】:

您的网关/路由器实际上有(至少)两个 IP 地址。您是在寻找一个面向您的节点还是另一个面向上游面向其他网络? 【参考方案1】:

这并不像听起来那么容易。 Java 是独立于平台的,所以我不确定如何在 Java 中做到这一点。我猜测 .NET 联系了某个网站,该网站将其报告回来。有几种方法可以走。首先,深入了解 ICMP 协议可能会为您提供所需的信息。您还可以跟踪您经过的 IP(您的路线)。当您遇到不在以下范围内的 IP 时:

10.0.0.0 - 10.255.255.255 172.16.0.0 - 172.31.255.255 192.168.0.0 - 192.168.255.255

它与您的 IP 相距一跳,并且可能与您的 IP 共享几个八位字节的信息。

祝你好运。我很想听到这个问题的明确答案。

【讨论】:

【参考方案2】:

如果有,请尝试使用 traceroute。

'traceroute -m 1 www.amazon.com' 会发出类似这样的信息:

traceroute to www.amazon.com (72.21.203.1), 1 hops max, 40 byte packets
 1  10.0.1.1 (10.0.1.1)  0.694 ms  0.445 ms  0.398 ms

解析第二行。是的,它很丑,但它会让你继续前进,直到有人发布更好的东西。

【讨论】:

【参考方案3】:

您最好使用 checkmyip.org 之类的东西,它会确定您的公共 IP 地址 - 不一定是您的第一跳路由器:在 Uni,我有一个“真实”IP 地址,而在家里,它是我本地路由器的公共 IP 地址IP 地址。

您可以解析返回的页面,或者找到另一个站点,让您只获取 IP 地址作为唯一的字符串。

(我的意思是用 Java/其他方式加载此 URL,然后获取您需要的信息)。

这应该完全独立于平台。

【讨论】:

【参考方案4】:

Matthew:是的,这就是我所说的“我可以使用网站上的服务获取我的 Internet IP”的意思。很抱歉自己流利了。

Brian/Nick:Traceroute 会很好,只是这些路由器中的许多都禁用了 ICMP,因此它总是停止。

我认为 traceroute 和 uPnP 的组合会奏效。这就是我打算做的,我只是希望我错过了一些明显的东西。

感谢大家的 cmets,所以听起来我没有遗漏任何明显的东西。为了发现网关,我已经开始实现一些 uPnP。

【讨论】:

【参考方案5】:

不幸的是,Java 并不像其他语言那样令人愉快。这是我所做的:

import java.io.*;
import java.util.*;

public class ExecTest 
    public static void main(String[] args) throws IOException 
        Process result = Runtime.getRuntime().exec("traceroute -m 1 www.amazon.com");

        BufferedReader output = new BufferedReader(new InputStreamReader(result.getInputStream()));
        String thisLine = output.readLine();
        StringTokenizer st = new StringTokenizer(thisLine);
        st.nextToken();
        String gateway = st.nextToken();
        System.out.printf("The gateway is %s\n", gateway);
    

这假定网关是第二个令牌而不是第三个。如果是,您需要添加一个额外的st.nextToken(); 以将标记器再提升一个位置。

【讨论】:

实际上它不适用于Windows-OS,因为traceroute在那里被称为tracert。【参考方案6】:

关于 UPnP:请注意,并非所有路由器都支持 UPnP。如果他们这样做,它可能会被关闭(出于安全原因)。因此,您的解决方案可能并不总是有效。

您还应该看看 NatPMP。

可以在 http://miniupnp.free.fr/ 找到一个简单的 UPnP 库,尽管它是 C 语言...

【讨论】:

【参考方案7】:

要克服 traceroute(基于 ICMP,广域命中)提到的问题,您可以考虑:

    traceroute 到您的公共 IP(避免广域命中,但仍然是 ICMP) 使用 ifconfig/ipconfig 之类的非 ICMP 实用程序(尽管存在可移植性问题)。 目前看来最好和最便携的解决方案是 shell 和解析 netstat(参见代码示例 here)

【讨论】:

【参考方案8】:

在 Windows 上解析 IPConfig 的输出将为您提供默认网关,而无需等待跟踪。

【讨论】:

【参考方案9】:

在 Windows、OSX、Linux 等平台上,使用

可以大大改善 Chris Bunch 的答案
netstat -rn

代替traceroute 命令。

网关的 IP 地址将出现在以default0.0.0.0 开头的行的第二个字段中。

这解决了尝试使用traceroute 时遇到的一些问题:

    在Windows上traceroute实际上是tracert.exe,所以代码中不需要O/S依赖 这是一个快速运行的命令 - 它从操作系统获取信息,而不是从网络获取信息 traceroute 有时会被网络屏蔽

唯一的缺点是需要不断地从netstat 输出读取行,直到找到正确的行,因为输出不止一行。

编辑:如果您使用的是 MAC(在 Lion 上测试),默认网关的 IP 地址位于以“default”开头的行的第二个字段中,或者在 第三个字段中以“0.0.0.0”开头的行的字段(在 Windows 7 上测试)

窗户:

网络目标网络掩码网关接口指标

0.0.0.0 0.0.0.0 192.168.2.254 192.168.2.46 10

苹果机:

目标网关标志 Refs 使用 Netif 过期

默认 192.168.2.254 UGSc 104 4 en1

【讨论】:

【参考方案10】:
    try
        String gateway;
        Process result = Runtime.getRuntime().exec("netstat -rn");

        BufferedReader output = new BufferedReader(new InputStreamReader(result.getInputStream()));

        String line = output.readLine();
        while(line != null)
            if ( line.trim().startsWith("default") == true || line.trim().startsWith("0.0.0.0") == true )
                break;      
            line = output.readLine();
        
        if(line==null) //gateway not found;
            return;

        StringTokenizer st = new StringTokenizer( line );
        st.nextToken();
        st.nextToken();
        gateway = st.nextToken();
        System.out.println("gateway is: "+gateway);


     catch( Exception e )  
        System.out.println( e.toString() );
        gateway = new String();
        adapter = new String();
    

【讨论】:

行也可以以0.0.0.0开头而不是default【参考方案11】:

您可以查询网址“http://whatismyip.com/automation/n09230945.asp”。 例如:

    BufferedReader buffer = null;
    try 
        URL url = new URL("http://whatismyip.com/automation/n09230945.asp");
        InputStreamReader in = new InputStreamReader(url.openStream());
        buffer = new BufferedReader(in);

        String line = buffer.readLine();
        System.out.println(line);
     catch (IOException e) 
        e.printStackTrace();
     finally 
        try 
            if (buffer != null) 
                buffer.close();
            
         catch (IOException e) 
            e.printStackTrace();
        
    

【讨论】:

【参考方案12】:

netstat -rn 的输出是特定于语言环境的。 在我的系统(locale=de)上,输出看起来像: ... 标准网关:10.22.0.1

所以没有以'default'开头的行。

所以使用 netstat 可能不是个好主意。

【讨论】:

那是什么操作系统?在 OSX 上,输出没有区域设置差异。【参考方案13】:

此版本连接到 www.whatismyip.com,读取站点内容并通过正则表达式搜索 ip 地址并将其打印到 cmd。它是对 MosheElishas 代码的一点改进

import java.io.BufferedReader;  
import java.io.IOException;  
import java.io.InputStreamReader; 
import java.net.URL;  
import java.util.regex.Matcher;  
import java.util.regex.Pattern;  

public class Main 

    public static void main(String[] args) 
        BufferedReader buffer = null;
        try 
            URL url = new URL(
                    "http://www.whatismyip.com/tools/ip-address-lookup.asp");
            InputStreamReader in = new InputStreamReader(url.openStream());
            buffer = new BufferedReader(in);
            String line = buffer.readLine();
            Pattern pattern = Pattern
                    .compile("(.*)value=\"(\\d+).(\\d+).(\\d+).(\\d+)\"(.*)");
            Matcher matcher;
            while (line != null) 
                matcher = pattern.matcher(line);
                if (matcher.matches()) 
                    line = matcher.group(2) + "." + matcher.group(3) + "."
                            + matcher.group(4) + "." + matcher.group(5);
                    System.out.println(line);
                
                line = buffer.readLine();
            
         catch (IOException e) 
            e.printStackTrace();

         finally 
            try 
                if (buffer != null) 
                    buffer.close();
                
             catch (IOException e) 
                e.printStackTrace();
            
        
    


import java.io.BufferedReader;  
import java.io.IOException;  
import java.io.InputStreamReader; 
import java.net.URL;  
import java.util.regex.Matcher;  
import java.util.regex.Pattern;  

public class Main 

    public static void main(String[] args) 
        BufferedReader buffer = null;
        try 
            URL url = new URL(
                    "http://www.whatismyip.com/tools/ip-address-lookup.asp");
            InputStreamReader in = new InputStreamReader(url.openStream());
            buffer = new BufferedReader(in);
            String line = buffer.readLine();
            Pattern pattern = Pattern
                    .compile("(.*)value=\"(\\d+).(\\d+).(\\d+).(\\d+)\"(.*)");
            Matcher matcher;
            while (line != null) 
                matcher = pattern.matcher(line);
                if (matcher.matches()) 
                    line = matcher.group(2) + "." + matcher.group(3) + "."
                            + matcher.group(4) + "." + matcher.group(5);
                    System.out.println(line);
                
                line = buffer.readLine();
            
         catch (IOException e) 
            e.printStackTrace();

         finally 
            try 
                if (buffer != null) 
                    buffer.close();
                
             catch (IOException e) 
                e.printStackTrace();
            
        
    

【讨论】:

【参考方案14】:

在windows中你可以使用以下命令:

ipconfig | findstr /i "Gateway"

这会给你这样的输出:

Default Gateway . . . . . . . . . : 192.168.2.1
Default Gateway . . . . . . . . . : ::

但是我无法使用 Java 运行此命令,等我弄清楚了再发布。

【讨论】:

【参考方案15】:

您可以使用netstat -rn 命令,该命令适用于 Windows、OSX、Linux 等平台。这是我的代码:

private String getDefaultAddress() 
        String defaultAddress = "";
        try 
            Process result = Runtime.getRuntime().exec("netstat -rn");

            BufferedReader output = new BufferedReader(new InputStreamReader(
                    result.getInputStream()));

            String line = output.readLine();
            while (line != null) 
                if (line.contains("0.0.0.0")) 

                    StringTokenizer stringTokenizer = new StringTokenizer(line);
                    stringTokenizer.nextElement(); // first element is 0.0.0.0
                    stringTokenizer.nextElement(); // second element is 0.0.0.0
                    defaultAddress = (String) stringTokenizer.nextElement();
                    break;
                

                line = output.readLine();

             // while
         catch (IOException e) 
            // TODO Auto-generated catch block
            e.printStackTrace();
        

        return defaultAddress;

 // getDefaultAddress

【讨论】:

【参考方案16】:

我不确定它是否适用于每个系统,但至少在这里我发现了这个:

import java.net.InetAddress;
import java.net.UnknownHostException;
public class Main

    public static void main(String[] args)
    
        try
        
            //Variables to find out the Default Gateway IP(s)
            String canonicalHostName = InetAddress.getLocalHost().getCanonicalHostName();
            String hostName = InetAddress.getLocalHost().getHostName();

            //"subtract" the hostName from the canonicalHostName, +1 due to the "." in there
            String defaultGatewayLeftover = canonicalHostName.substring(hostName.length() + 1);

            //Info printouts
            System.out.println("Info:\nCanonical Host Name: " + canonicalHostName + "\nHost Name: " + hostName + "\nDefault Gateway Leftover: " + defaultGatewayLeftover + "\n");
            System.out.println("Default Gateway Addresses:\n" + printAddresses(InetAddress.getAllByName(defaultGatewayLeftover)));
         catch (UnknownHostException e)
        
            e.printStackTrace();
        
    
    //simple combined string out of the address array
    private static String printAddresses(InetAddress[] allByName)
    
        if (allByName.length == 0)
        
            return "";
         else
        
            String str = "";
            int i = 0;
            while (i < allByName.length - 1)
            
                str += allByName[i] + "\n";
                i++;
            
            return str + allByName[i];
        
    

对我来说,这会产生:

Info:
Canonical Host Name: PCK4D-PC.speedport.ip
Host Name: PCK4D-PC
Default Gateway Leftover: speedport.ip

Default Gateway Addresses:
speedport.ip/192.168.2.1
speedport.ip/fe80:0:0:0:0:0:0:1%12

我需要对其他系统/配置/PC-Gateway-Setups 进行更多测试,以确认它是否可以在任何地方工作。有点怀疑,但这是我发现的第一个。

【讨论】:

以上是关于如何在 Java 中确定我的路由器/网关的 IP?的主要内容,如果未能解决你的问题,请参考以下文章

Centos如何设置IP地址,LINUX怎么修改IP地址

为啥默认网关地址有时候是本网络里第一个可用ip地址,而有时候是广...

不同网段,在路由器上如何设置网关

为啥我的电脑ping不通别人

我的ubuntu 有三个IP,请问我怎么设置主IP?

如何解决用固定IP,填入正确的DNS却不能上网