§ 实验要求:
实现一个既可以支持命令行输入,也可以进行交互式输入的基本nslookup程序。要求实现域名和IP地址间的转换(输入域名输出IPV4地址;输入IP地址输出域名(对于得不到域名的情况会返回IP地址,可以直接输出这个IP地址也可以输出提示信息说明“域名没有找到”))
§ 截屏输入域名的结果
§ 截屏输入IP地址的结果
为什么反查不了域名的结果解析:
如果输入的是域名,先查找本地有没有缓存对应的地址和域名的映射,如果没有会将其发往DNS服务器查询对应的映射。也就是说getHostName可能会get到空值的情况,在这种情况下会自动向DNS服务器去反向查询域名,如果能查到就返回域名,查不到就直接把IP地址当成域名。由于安全问题(一开始我们用nslookup就可以看到返回的服务器并不是baidu,而是它的外壳),再加上网络过于复杂(IP相对域名来说太不稳定,域名经常好几年不变但是IP经常变化,导致了现在某个IP对应的域名过段时间或许就对到另一个域名上了;或者直接是域名不一样但是IP是一样的,这时候如果返回所有域名对安全性也没有保证),国内各大网站的服务器基本都不允许通过这种方式反向查询域名,所以基本上都查不到直接返回IP地址。但是有一个是绝对查得出来的,那就是本机上的IP地址(因为本机上IP的映射一定是保存在本机文件里面的,所以能找到)
§ 源代码:
import java.net.*; import java.util.regex.Pattern; import java.io.*; public class nslookup { public static void main(String[] args) { if (args.length > 0) { for (int i = 0; i < args.length; i++) { lookup(args[i]); } } else { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); System.out.println("Enter the domain names or IP addresses. Enter \"exit\" to quit."); try { while (true) { String host = in.readLine(); if (host.equalsIgnoreCase("exit")) { break; } lookup(host); System.out.println("Enter the domain names or IP addresses. Enter \"exit\" to quit."); } } catch (IOException e) { e.printStackTrace(); } } } private static void lookup(String host) { if(isDomain(host)) //输入为域名 { // TODO Auto-generated method stub try { //得到的包含域名部分和IP部分,仍需分离 InetAddress address = InetAddress.getByName(host); System.out.println("The IP address of "+address.getHostName()+" is "); //分离出IP部分 System.out.println(address.getHostAddress()); } catch (UnknownHostException e) { e.printStackTrace(); } } else //输入为IP地址 { // TODO Auto-generated method stub //分离出域名部分 try { InetAddress address = InetAddress.getByName(host); System.out.println("The domain name is: "); System.out.println(address.getHostName()); } catch (UnknownHostException e) { e.printStackTrace(); } } } private static boolean isDomain(String host) { String[] part = host.split("\\."); if (part.length == 4) { for (String pa : part) { if (!isNumeric(pa)) { return true; } } return false; } else { return true; } } public static boolean isNumeric(String str) { Pattern pattern = Pattern.compile("[0-9]*"); return pattern.matcher(str).matches(); } }
实验方法分析:
首先用isDomain(host)判断是输入是域名还是IP地址。二者都会先用getByName函数获得域名和IP地址,getByName函数区别于getAllByName函数,后者是可以获取域名所有的IP地址(见下面的加强版程序),而前者只会取其一。用getByName得到的域名和IP地址存放在InetAddress类型的变量中(getAllByName则存放在InetAddress类型的数组中,并且每一个下标指向的是域名+IP,区别在于每个下标的IP地址不同[域名是一样的]),然后利用getHostName()函数得到其中的域名部分,用getHostAdreess()函数得到IP地址部分。最后输出即可。
(2)编写加强的nslookupAdvanced程序
§ 实验要求:
在源程序的基础之上在输入域名时输出全部地址,同时如果查询的域名或者IP在本主机上还要输出对应的端口号,如果不在本主机上也需要给相应的提示信息
§ 找到至少一个绑定到多个IP地址上的域名,截屏输入域名的结果
§ 截屏输入IP地址的结果
实验方法分析:
上面的分析已经讲了要得到域名的所有IP地址,用getAllByName替代getByName即可,然后用getByInetAddress函数获取到IP地址所对应的端口号,若获取得到的为null,表示获取不到端口号,也就是说这个IP地址不是本机的。若不为空,表示根据本机的IP地址获取到了端口号,然后输出即可。
§ 源代码:
import java.net.*; import java.util.regex.Pattern; import java.io.*; public class nslookupAdvanced { public static void main(String[] args) { if (args.length > 0) { for (int i = 0; i < args.length; i++) { lookupAdvanced(args[i]); } } else { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); System.out.println("Enter the domain names or IP addresses. Enter \"exit\" to quit."); try { while (true) { String host = in.readLine(); if (host.equalsIgnoreCase("exit")) { break; } lookupAdvanced(host); System.out.println("Enter the domain names or IP addresses. Enter \"exit\" to quit."); } } catch (IOException e) { e.printStackTrace(); } } } private static void lookupAdvanced(String host) { if(isDomain(host)) //输入为域名 { // TODO Auto-generated method stub try { //得到的数组(每一位都)包含域名部分和IP部分,仍需分离 InetAddress[] address = InetAddress.getAllByName(host); System.out.println("The IP address of "+address[0].getHostName()+" is "); //分离出IP部分 for (int i = 0; i < address.length; i++) { /*System.out.println(address.length); 输出为2,也就是说baidu.com这个域名有两个IP地址, 每个address数组下标都包含域名+IP地址,区别在于每个下标的IP地址不一样 */ System.out.println(address[i].getHostAddress()); } //查找端口号 NetworkInterface ni = NetworkInterface.getByInetAddress(address[0]); if (ni != null) { //非空即表示为本机 System.out.println(ni); } else { //非本机,不可查看端口号 System.out.println("address " + address[0] + " is not local address."); } } catch (UnknownHostException e) { e.printStackTrace(); } catch (SocketException e) { e.printStackTrace(); } } else //输入为IP地址 { // TODO Auto-generated method stub //分离出域名部分 try { InetAddress[] address = InetAddress.getAllByName(host); System.out.println("The domain name is: "); System.out.println(address[0].getHostName()); //查找端口号 NetworkInterface ni = NetworkInterface.getByInetAddress(address[0]); if (ni != null) { //非空即表示为本机 System.out.println(ni); } else { //非本机,不可查看端口号 System.out.println("address " + address[0] + " is not local address."); } } catch (UnknownHostException e) { e.printStackTrace(); } catch (SocketException e) { e.printStackTrace(); } } } private static boolean isDomain(String host) { String[] part = host.split("\\."); if (part.length == 4) { for (String pa : part) { if (!isNumeric(pa)) { return true; } } return false; } else { return true; } } public static boolean isNumeric(String str) { Pattern pattern = Pattern.compile("[0-9]*"); return pattern.matcher(str).matches(); } }