DNS编程实验--域名与IP的相互转换
§ 实验要求:
实现一个既可以支持命令行输入,也可以进行交互式输入的基本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();
}
}