Как я могу определить IP моего маршрутизатора / шлюза на Java?

Как я могу определить IP моего маршрутизатора / шлюза на Java? Я могу легко получить свой IP. Я могу получить свой IP-адрес в Интернете с помощью службы на веб-сайте. Но как я могу определить IP своего шлюза?

Это довольно просто в .NET, если вы знаете, что делать. Но как это сделать на Java?

Ответов (16)

Решение

К сожалению, в 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 предоставит вам шлюз по умолчанию, не дожидаясь трассировки.

Эта версия подключается к www.whatismyip.com, считывает содержимое сайта, выполняет поиск с помощью регулярных выражений по IP-адресу и выводит его в cmd. Это небольшое улучшение Кодекса Моше-Элишаса

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

В Windows вы можете просто использовать следующую команду:

ipconfig | findstr /i "Gateway"

Что даст вам такой результат:

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

Однако я не могу запустить эту команду с Java, опубликую, когда я это выясню.

Вы можете использовать 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

Я не уверен, работает ли он во всех системах, но, по крайней мере, здесь я нашел это:

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

Мне бы потребовались дополнительные тесты на других системах / конфигурациях / настройках шлюза ПК, чтобы подтвердить, работает ли он везде. Вроде сомневаюсь, но это было первое, что я нашел.

Попробуйте обстрелять 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

Разберите вторую строку. Да, это некрасиво, но это поможет, пока кто-нибудь не опубликует что-нибудь получше.

Это не так просто, как кажется. 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 подойдет, за исключением того факта, что на многих из этих маршрутизаторов отключен ICMP, и поэтому он всегда зависает.

Думаю, комбинация traceroute и uPnP сработает. Это то, что я планировал сделать, я просто надеялся, что упустил что-то очевидное.

Спасибо всем за ваши комментарии, так что похоже, что я не упускаю ничего очевидного. Я начал внедрять некоторые части uPnP, чтобы обнаружить шлюз.

Возможно, вам будет лучше использовать что-то вроде checkmyip.org, который определит ваш общедоступный IP-адрес - не обязательно ваш маршрутизатор первого перехода: в Uni у меня есть «настоящий» IP-адрес, тогда как дома это общедоступный IP-адрес моего локального маршрутизатора.

Вы можете проанализировать возвращаемую страницу или найти другой сайт, который позволяет вам просто вернуть IP-адрес в качестве единственной строки.

(Я имею в виду загрузить этот URL-адрес в Java / что-то еще, а затем получить необходимую информацию).

Это должно быть полностью независимым от платформы.

Что касается UPnP: имейте в виду, что не все маршрутизаторы поддерживают UPnP. А если они это сделают, то его можно выключить (по соображениям безопасности). Так что ваше решение может не всегда работать.

Вам также следует взглянуть на NatPMP.

Простую библиотеку для UPnP можно найти на http://miniupnp.free.fr/ , хотя она на C ...

Чтобы преодолеть проблемы, упомянутые с traceroute (основанное на ICMP, широкое попадание), вы можете подумать:

  1. traceroute на ваш общедоступный IP-адрес (избегает попадания в глобальную область, но все же ICMP)
  2. Используйте служебную программу, отличную от ICMP, например ifconfig / ipconfig (однако при этом возникают проблемы с переносимостью).
  3. Лучшим и наиболее переносимым решением на данный момент является оболочка и синтаксический анализ netstat (см. Пример кода здесь )

В Windows, OSX, Linux и т. Д. Ответ Криса Банча можно значительно улучшить, используя

netstat -rn

вместо traceroute команды.

IP-адрес вашего шлюза появится во втором поле строки, которая начинается с default или 0.0.0.0 .

Это позволяет обойти ряд проблем с попыткой использования traceroute :

  1. в Windows tracerouteна самом деле tracert.exe, поэтому нет необходимости в зависимостях O / S в коде
  2. это быстрая команда для запуска - она ​​получает информацию от O / S, а не из сети
  3. traceroute иногда блокируется сетью

Единственным недостатком является то, что необходимо будет продолжать читать строки netstat вывода до тех пор, пока не будет найдена нужная строка, поскольку будет более одной строки вывода.

РЕДАКТИРОВАТЬ: IP-адрес шлюза по умолчанию находится во втором поле строки, которая начинается с 'default', если вы используете MAC (проверено на Lion), или в третьем поле строки, начинающейся с '0.0.0.0' ( протестировано на Windows 7)

Windows:

Метрика интерфейса шлюза маски сети назначения

0.0.0.0 0.0.0.0 192.168.2.254 192.168.2.46 10

Mac:

Флаги целевого шлюза Refs Use Netif Expire

по умолчанию 192.168.2.254 UGSc 104 4 en1

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

Вы можете запросить URL " 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();
        }
    }

вывод netstat -rn зависит от локали. в моей системе (locale = de) вывод выглядит так: ... Standardgateway: 10.22.0.1

поэтому нет строки, начинающейся со слова «по умолчанию».

поэтому использование netstat может быть плохой идеей.