如何确定Java中路由器/网关的IP?
如何确定Java中路由器/网关的IP?我可以很容易地获得我的IP。我可以使用网站上的服务获取互联网IP。但是,如何确定网关的IP?
如果我们知道自己的方法,那么在.NET中这很容易。但是,我们如何用Java做到这一点呢?
解决方案
回答
那并不像听起来那么容易。 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 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
解析第二行。是的,这很丑陋,但除非有人发布更好的内容,否则它会让我们继续前进。
回答
使用checkmyip.org之类的东西可能会更好,它可以确定公共IP地址,不一定是第一跳路由器:在Uni,我有一个"真实" IP地址,而在家里,这是我本地路由器的公共IP地址。
我们可以解析返回的页面,或者找到另一个站点,该站点允许我们仅将IP地址作为唯一字符串取回。
(我的意思是用Java /任何方式加载此URL,然后获取所需的信息)。
这应该完全独立于平台。
回答
马修:是的,这就是我的意思,"我可以使用网站上的服务获取互联网IP"。很抱歉成为glib。
Brian / Nick:Traceroute会很好,除非这些路由器中有许多禁用了ICMP,因此它总是停滞。
我认为将traceroute和uPnP结合使用是可行的。那就是我打算做的事情,只是希望我遗漏了一些明显的东西。
谢谢大家的评论,所以听起来我似乎没有任何明显的缺失。我已经开始实现uPnP的一些功能以发现网关。
回答
不幸的是,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();"以使令牌生成器再增加一个位置。
回答
关于UPnP:请注意,并非所有路由器都支持UPnP。如果这样做,则可以将其关闭(出于安全原因)。因此,解决方案可能并不总是有效。
我们还应该看看NatPMP。
可以在http://miniupnp.free.fr/找到一个简单的UPnP库,尽管它在C语言中。
回答
为了克服traceroute提到的问题(基于ICMP的广域网攻击),我们可以考虑:
- 跟踪到公共IP的路由(避免广域网攻击,但仍然是ICMP)
- 使用非ICMP实用程序,如ifconfig / ipconfig(尽管与此相关的可移植性问题)。
- 目前看来,最好,最便携的解决方案是对netstat进行外壳和解析(请参见此处的代码示例)
回答
在Windows上,解析IPConfig的输出将为我们提供默认网关,而无需等待跟踪。
回答
在Windows,OSX,Linux等系统上,Chris Bunch的答案可以通过使用来大大改善
netstat -rn
代替traceroute
命令。
网关的IP地址将出现在以" default"或者" 0.0.0.0"开头的行的第二个字段中。
尝试使用traceroute
可以解决许多问题:
- 在Windows上," traceroute"实际上是" tracert.exe",因此代码中不需要O / S依赖项
- 这是一个快速运行的命令-它从操作系统(而不是网络)获取信息
- traceroute有时会被网络阻止
唯一的缺点是必须保持从netstat输出中读取行,直到找到正确的行为止,因为会有多行输出。
编辑:如果我们使用的是MAC(在Lion上测试),则默认网关的IP地址位于以"默认"开头的行的第二个字段中,或者位于以" 0.0.0.0"开头的行的第三个字段中(在Windows 7上测试)
视窗:
Network Destination Netmask Gateway Interface Metric 0.0.0.0 0.0.0.0 192.168.2.254 192.168.2.46 10
苹果电脑:
Destination Gateway Flags Refs Use Netif Expire default 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(); }
回答
我们可以查询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)上,输出如下所示:
...
标准网关:10.22.0.1
因此,没有以" default"开头的行。
因此使用netstat可能不是一个好主意。