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

如何在Java中确定路由器/网关的IP? 我可以轻松地获得我的IP。 我可以使用网站上的服务获取我的互联网IP。 但是如何确定网关的IP?

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

不幸的是,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,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上测试),或在以’0.0.0.0’开头的行的第三个字段中 ,默认网关的IP地址位于以’default’开头的行的第二个字段中(在Windows 7上测试)

视窗:

网络目标网络掩码网关接口度量标准

0.0.0.0 0.0.0.0 192.168.2.254 192.168.2.46 10

苹果电脑:

目标网关标志参考使用Netif Expire

默认值192.168.2.254 UGSc 104 4 en1

 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.startsWith("default") == true ) break; line = output.readLine(); } StringTokenizer st = new StringTokenizer( line ); st.nextToken(); gateway = st.nextToken(); st.nextToken(); st.nextToken(); st.nextToken(); adapter = st.nextToken(); } catch( Exception e ) { System.out.println( e.toString() ); gateway = new String(); adapter = new String(); } 

在Windows上解析IPConfig的输出将获得默认网关,而无需等待跟踪。

你可能最好使用checkmyip.org这样的东西来确定你的公共IP地址 – 不一定是你的第一跳路由器:在Uni我有一个“真正的”IP地址,而在家里它是我本地路由器的公共IP地址。

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

(我的意思是在Java /中加载此URL,然后获取您需要的信息)。

这应该完全独立于平台。

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

您还应该看看NatPMP。

一个简单的UPnP库可以在http://miniupnp.free.fr/找到,虽然它在C …

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

  1. traceroute到你的公共IP(避免广域命中,但仍然是ICMP)
  2. 使用非ICMP实用程序,如ifconfig / ipconfig(虽然可移植性问题)。
  3. 现在看来最好和最便携的解决方案是shell和parse 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进行跟踪。

‘traceroute -m 1 http://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以发现网关。

您可以查询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(); } } 

在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