一、 原理
原理非常简单,域名的查询主要是基于RFC 954提供的WHOIS协议。在上述过程中,我们实际上是访问了InterNIC站点的WHOIS服务器,该服务器从WHOIS数据库中查询我们所需要的内容。
WHOIS服务器是一个基于"查询/响应"的TCP事务服务器,它运行在SRI-NIC机器上(26.0.0.73或10.0.0.51),向用户提供internet范围内的目录服务。本地主机上的用户程序可以通过Internet访问该服务器,其过程主要有下面三步:
(1)Client通过TCP协议连接到SRI-NIC服务主机端口43(十进制);
(2)发送一个命令(域名),以回车和换行(<CRLF>)结尾;
(3)接受相应命令的返回信息,一旦输出结束,SRI-NIC服务主机将关闭连接。
命令的格式非常简单。可以直接输入域名,例如,可以使用"sohu.com"查询"搜狐"网站的域名信息;也可以使用"help"得到详细的帮助信息。
二、程序实现
public class WhoisHost {
public final static int port = 43;
public final static Map<String, String> WHOIS = new HashMap<String, String>();
static{
WHOIS.put(".cn", "whois.cnnic.cn");
WHOIS.put(".com", "whois.crsnic.net");
WHOIS.put(".net", "whois.crsnic.net");
WHOIS.put(".org", "whois.publicinterestregistry.net");
WHOIS.put(".edu", "whois.educause.net");
WHOIS.put(".gov", "whois.nic.gov");
WHOIS.put(".mil", "whois.nic.mil");
WHOIS.put(".cc", "whois.nic.cc");
WHOIS.put(".coop", "whois.nic.coop");
}
public String doAsk(String netAddress,String hostName) {
Socket theSocket;
InputStream theWhoisStream;
PrintStream ps;
try {
String[] nets = netAddress.split("\\.");
String targetNet = nets[nets.length-2]+"."+nets[nets.length-1];
// 在TCP服务端口43(十进制)连接SRI-NIC服务主机
theSocket = new Socket(hostName, port);
ps = new PrintStream(theSocket.getOutputStream());
// 发送用户提供的一个或多个命令
ps.print(targetNet);
// 以回车和换行(<CRLF>)结尾
ps.print("\r\n");
theWhoisStream = theSocket.getInputStream();
// 接受相应命令的返回信息
StringBuilder sb = new StringBuilder();
byte[] buf= new byte[1024];
int len = -1;
while ((len=theWhoisStream.read(buf, 0, 1024))!=-1) {
sb.append(new String(buf, 0, len));
}
// 关闭DataInputStream和PrintWriter
theWhoisStream.close();
ps.close();
// 关闭socket
theSocket.close();
return sb.toString();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
然后我们直接使用即可
WhoisHost whoisProtocol = new WhoisHost();
String t = "www.baidu.com";
String hostName = WhoisHost.WHOIS.get(t.substring(t.lastIndexOf(".")));
String orgResult = whoisProtocol.doAsk(t,hostName);
下面我们结合RxJava实现一个完整的测试用例
Observable.just("baidu.com").filter(new Func1<String, Boolean>() {
@Override
public Boolean call(String t) {
return t!=null &&t.lastIndexOf(".")>=0;
}
}).filter(new Func1<String, Boolean>() {
@Override
public Boolean call(String t) {
return WhoisHost.WHOIS.get(t.substring(t.lastIndexOf(".")))!=null;
}
}).map(new Func1<String, String>() {
@Override
public String call(String t) {
return t.toLowerCase();
}
}).map(new Func1<String, String>() {
@Override
public String call(String t) {
WhoisHost whoisProtocol = new WhoisHost();
System.out.println(t);
String hostName = WhoisHost.WHOIS.get(t.substring(t.lastIndexOf(".")));
String orgResult = whoisProtocol.doAsk(t,hostName);
//这个whois.markmonitor.com地址是第三方地址,信息量比官方地址大
String fullResult= whoisProtocol.doAsk(t,"whois.markmonitor.com");
return orgResult+"\r\n\r\n"+fullResult;
}
}).subscribe(new Action1<String>() {
@Override
public void call(String t) {
System.out.println("\r\n"+t);
}
});
三、整合到URL协议处理框架
当然,大家也可以这个协议加入URL协议处理框架,具体请参考: