DNS编程实验--域名与IP的相互转换

时间:2024-02-24 11:01:22
(1)编写基本的nslookup程序

§   实验要求:

实现一个既可以支持命令行输入,也可以进行交互式输入的基本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();
	}
}