簡體   English   中英

如何在 Java 中確定路由器/網關的 IP?

[英]How can I determine the IP of my router/gateway in Java?

如何在 Java 中確定路由器/網關的 IP? 我可以很容易地獲得我的IP。 我可以使用網站上的服務獲取我的互聯網 IP。 但是如何確定網關的 IP?

如果您了解自己的方法,這在 .NET 中會比較容易。 但是你如何在 Java 中做到這一點呢?

在 Windows、OSX、Linux 等上,使用 Chris Bunch 的答案可以大大改進

netstat -rn

代替traceroute命令。

您網關的 IP 地址將出現在以default0.0.0.0開頭的行的第二個字段中。

這解決了嘗試使用traceroute的許多問題:

  1. Windows 上的traceroute實際上是tracert.exe ,因此代碼中不需要 O/S 依賴項
  2. 這是一個快速運行的命令 - 它從 O/S 獲取信息,而不是從網絡獲取
  3. 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

蘋果:

目標網關標志引用使用 Netif 過期

默認192.168.2.254 UGSc 104 4 en1

不幸的是,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 上解析 IPConfig 的輸出將為您提供默認網關,而無需等待跟蹤。

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

您最好使用諸如 checkmyip.org 之類的東西,它會確定您的公共 IP 地址 - 不一定是您的第一跳路由器:在 Uni 我有一個“真實”的 IP 地址,而在家里,它是我本地路由器的公共 IP 地址。

您可以解析返回的頁面,或者找到另一個站點,該站點允許您將 IP 地址作為唯一的字符串返回。

(我的意思是在 Java 中加載這個 URL/任何東西,然后獲取你需要的信息)。

這應該是完全獨立於平台的。

關於 UPnP:請注意,並非所有路由器都支持 UPnP。 如果他們這樣做,它可能會被關閉(出於安全原因)。 因此,您的解決方案可能並不總是有效。

您還應該看看 NatPMP。

可以在http://miniupnp.free.fr/找到一個簡單的 UPnP 庫,盡管它是在 C 中...

要克服 traceroute(基於 ICMP,廣域命中)提到的問題,您可以考慮:

  1. traceroute 到您的公共 IP(避免廣域命中,但仍然是 ICMP)
  2. 使用非 ICMP 實用程序,如 ifconfig/ipconfig(盡管存在可移植性問題)。
  3. 目前看來最好和最便攜的解決方案是 shell 和解析 netstat(請參閱此處的代碼示例)

netstat -rn 的輸出是特定於語言環境的。 在我的系統 (locale=de) 上,輸出如下所示: ... Standardgateway: 10.22.0.1

所以沒有以“default”開頭的行。

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

此版本連接到 www.whatismyip.com,讀取站點內容並通過正則表達式搜索 ip 地址並將其打印到 cmd。 它是對 MosheElishas Code 的一點改進

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

這並不像聽起來那么容易。 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,並且可能與您的 IP 共享幾個八位字節的信息。

祝你好運。 我很想聽到這個問題的明確答案。

如果你有的話,試着去追蹤路由。

'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

解析第二行。 是的,它很丑,但它會讓你繼續前進,直到有人發布更好的東西。

馬修:是的,這就是我所說的“我可以使用網站上的服務獲取我的互聯網 IP”。 抱歉我是油嘴滑舌的。

Brian/Nick:Traceroute 應該沒問題,除了很多這些路由器都禁用了 ICMP 並因此它總是停滯不前。

我認為 traceroute 和 uPnP 的組合會奏效。 這就是我打算做的,我只是希望我遺漏了一些明顯的東西。

謝謝大家的評論,所以聽起來我沒有遺漏任何明顯的東西。 我已經開始實施一些 uPnP 以發現網關。

在 Windows 中,您可以只使用以下命令:

ipconfig | findstr /i "Gateway"

這將為您提供如下輸出:

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

但是我無法使用 Java 運行此命令,當我弄清楚這一點時會發布。

您可以查詢網址“ 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();
        }
    }

您可以使用在 Windows、OSX、Linux 等平台上可用的netstat -rn命令。 這是我的代碼:

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

我不確定它是否適用於每個系統,但至少在這里我發現了這一點:

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 網關設置進行更多測試,以確認它是否適用於所有地方。 有點懷疑,但這是我發現的第一個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM