原帖地址 http://blog.youkuaiyun.com/stevexk/article/details/2270346TestDns.java
import java.io.IOException;
import java.io.InterruptedIOException;
import java.lang.reflect.UndeclaredThrowableException;
import java.net.ConnectException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.NoRouteToHostException;
import java.net.UnknownHostException;
public class TestDns {
public static void main(String[] args){
// get the parameters
//
int retry = 2;
int port = 53;
int timeout = 3000;
// Host to lookup?
//
String lookup = "www.google.com";
if (lookup == null || lookup.length() == 0) {
// Get hostname of local machine for future DNS lookups
//
try {
lookup = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException ukE) {
// Recast the exception as a Service Monitor Exception
//
ukE.fillInStackTrace();
throw new UndeclaredThrowableException(ukE);
}
}
// get the address and DNS address request
//
InetAddress ipv4Addr = null;
try {
ipv4Addr = InetAddress.getByName("165.87.13.129");
} catch (UnknownHostException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
DNSAddressRequest request = new DNSAddressRequest(lookup);
int serviceStatus = -1;
DatagramSocket socket = null;
long responseTime = -1;
try {
socket = new DatagramSocket();
socket.setSoTimeout(timeout); // will force the
// InterruptedIOException
for (int attempts = 0; attempts <= retry && serviceStatus != 1; attempts++) {
try {
// Send DNS request
//
byte[] data = request.buildRequest();
DatagramPacket outgoing = new DatagramPacket(data, data.length, ipv4Addr, port);
long sentTime = System.currentTimeMillis();
socket.send(outgoing);
// Get DNS Response
//
byte[] buffer = new byte[512];
DatagramPacket incoming = new DatagramPacket(buffer, buffer.length);
socket.receive(incoming);
responseTime = System.currentTimeMillis() - sentTime;
// Validate DNS Response
// IOException thrown if packet does not decode as expected.
request.verifyResponse(incoming.getData(), incoming.getLength());
System.out.println(incoming.getAddress());
System.out.println("poll: valid DNS request received, responseTime= " + responseTime + "ms");
serviceStatus = 1;
} catch (InterruptedIOException ex) {
// Ignore, no response received.
}
}
} catch (NoRouteToHostException e) {
e.fillInStackTrace();
System.out.println("No route to host exception for address: " + ipv4Addr);
} catch (ConnectException e) {
// Connection refused. Continue to retry.
//
e.fillInStackTrace();
System.out.println("Connection exception for address: " + ipv4Addr);
} catch (IOException ex) {
ex.fillInStackTrace();
System.out.println("IOException while polling address: " + ipv4Addr);
} finally {
if (socket != null)
socket.close();
}
// Store response time if available
//
if (serviceStatus == 1) {
System.out.println("response time="+responseTime);
}
}
}
DNSAddressRequest.java
//
// This file is part of the OpenNMS(R) Application.
//
// OpenNMS(R) is Copyright (C) 2002-2003 The OpenNMS Group, Inc. All rights reserved.
// OpenNMS(R) is a derivative work, containing both original code, included code and modified
// code that was published under the GNU General Public License. Copyrights for modified
// and included code are below.
//
// OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
//
// Copyright (C) 1999-2001 Oculan Corp. All rights reserved.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// For more information contact:
// OpenNMS Licensing <license@opennms.org>
// http://www.opennms.org/
// http://www.opennms.com/
//
import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.IOException;
/**
* <P>
* DNSInputStrean extends a ByteArrayInputStream and has methods to decode the
* data of a DNS response to an address resquest.
* </P>
*
* @author <A HREF="mailto:sowmya@opennms.org">Sowmya </A>
* @author <A HREF="http://www.opennms.org">OpenNMS </A>
*
*/
public class DNSInputStream extends ByteArrayInputStream {
/**
* <P>
* Constructs a new input stream for decoding DNS records.
* </P>
*
* @param data
* The array of data to pass to the base class.
*/
public DNSInputStream(byte[] data) {
super(data);
}
/**
* <P>
* Constructs a DNSInputStream object from the byte array.
* </P>
*
* @param data
* byte array containing the response data
* @param off
* offset of the data in the byte array
* @param len
* length of the byte array
*/
public DNSInputStream(byte[] data, int off, int len) {
super(data, off, len);
}
/**
* <P>
* Read a byte off the input stream.
* </P>
*
* @return The integer read.
*
* @exception java.io.IOException
* Thrown if the end-of-file is encountered trying to read
* the next byte.
*/
public int readByte() throws IOException {
int rc = read();
if (rc == -1)
throw new EOFException("end of buffer on read");
return rc;
}
/**
* <P>
* Read a 'short' off the input stream.
* </P>
*
* @return The short from the input stream.
*
* @exception java.io.IOException
* Thrown if the end-of-file is encountered trying to read
* the next short.
*/
public int readShort() throws IOException {
return (readByte() << 8 | readByte());
}
/**
* <P>
* Read an 'int' off the input stream.
* </P>
*
* @return The int from the input stream.
*
* @exception java.io.IOException
* Thrown if there is an error while read.
*/
public long readInt() throws IOException {
long rc = 0;
for (int i = 0; i < 4; i++)
rc = (rc << 8) | readByte();
return rc;
}
/**
* <P>
* Read a 'string' off the input stream.
* </P>
*
* @return the string from the input stream
*
* @exception java.io.IOException
* Thrown if there is an error while read
*/
public String readString() throws IOException {
int len = readByte();
if (len == 0) {
return "";
}
byte[] buffer = new byte[len];
int rc = read(buffer);
if (rc == -1 || rc != len)
throw new EOFException("end of file while reading array");
return new String(buffer);
}
/**
* <P>
* The readDomainName method is used to read an entire domain name from the
* stream. The string returned will be the concatentation of several
* substrings, each substring in the record is separated by a '.'(dot). For
* more information see the RFC for the distributed name service.
* </P>
*
* @return The domain name string.
*
* @exception java.io.IOException
* Thrown if an error occurs decoding the string from the
* stream.
*/
public String readDomainName() throws IOException {
//
// Check to make sure that we are not going
// to index the array and generate an bounds
// exception.
//
if (pos >= count)
throw new EOFException("EOF reading domain name");
//
// check the length byte. If the upper two bits are
// not set then it is a normal string and can be
// decoded using the readString() method.
//
if ((buf[pos] & 0xc0) == 0) {
String label = readString();
if (label.length() > 0) {
//
// get the next component(s) of the
// domain name. This is a recursive call.
// If the length is not equal to null then
// append the tail and return the new domain
// name.
//
String tail = readDomainName();
if (tail.length() > 0)
label = label + '.' + tail;
}
return label;
}
//
// If this point in the code is reached then
// compression is being used!
//
//
// If the upper two bits were set then this is a special
// encoding that points us to somewhere else in the record!
// We have to read that part of the record and to get the
// next element in the stream.
//
// Throw an I/O exception if the compression offset is
// malformed.
//
if ((buf[pos] & 0xc0) != 0xc0)
throw new IOException("Invalid domain name compression offset");
//
// read the short that is the pointer to the other
// part of the stream. Note buf is a protected buffer.
//
int offset = readShort() & 0x3fff;
DNSInputStream dnsIn = new DNSInputStream(buf, offset, buf.length - offset);
return dnsIn.readDomainName();
}
/**
* <P>
* Reads the resource record from the input stream.
* </P>
*
* @return The DNSAddressRR that is in response to the address request.
*
* @exception java.io.IOException
* Thrown if data does not decode to a DNSAddressRRl.
*/
public DNSAddressRR readRR() throws IOException {
String rrName = readDomainName();
int rrType = readShort();
int rrClass = readShort();
long rrTTL = readInt();
int rrDataLen = readShort();
//
// Convert the length of data in this byte array input stream
// into a "substream" of data. The only way this could get
// complicated is if there are multiple threads using this
// stream. If that is the case then synchronization code
// should be used to wrap the next two lines -- Weave
//
DNSInputStream rrDNSIn = new DNSInputStream(buf, pos, rrDataLen);
pos += rrDataLen;
try {
//
// Create the route record and return it to
// the caller.
//
DNSAddressRR rr = new DNSAddressRR(rrName, rrType, rrClass, rrTTL, rrDNSIn);
return rr;
} catch (Exception ex) {
throw new IOException("Unknown DNSAddressRR (type " + " (" + rrType + "))" + " Originating Exception: " + ex.getMessage());
}
}
}
DNSAddressRR.java
//
// This file is part of the OpenNMS(R) Application.
//
// OpenNMS(R) is Copyright (C) 2002-2003 The OpenNMS Group, Inc. All rights reserved.
// OpenNMS(R) is a derivative work, containing both original code, included code and modified
// code that was published under the GNU General Public License. Copyrights for modified
// and included code are below.
//
// OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
//
// Copyright (C) 1999-2001 Oculan Corp. All rights reserved.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// For more information contact:
// OpenNMS Licensing <license@opennms.org>
// http://www.opennms.org/
// http://www.opennms.com/
//
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* <P>
* Holds a DNS resource record which is a DNS response that gives the IP address
* of a particular hostname. A resource record typically has:
* </P>
*
* <TABLE BORDER=0>
* <TH>
* <TD>Element</TD>
* <TD>Description</TD>
* </TH>
* <TR>
* <TD>Name</TD>
* <TD>Domain name that the resource record describes.</TD>
* </TR>
* <TR>
* <TD>Type</TD>
* <TD>Type of RR.</TD>
* </TR>
* <TR>
* <TD>Class</TD>
* <TD>RR Class.</TD>
* </TR>
* <TR>
* <TD>TTL</TD>
* <TD>Time-To-Live for the RR.</TD>
* </TR>
* <TR>
* <TD>RDLEN</TD>
* <TD>Length of the following data.</TD>
* </TR>
* <TR>
* <TD>Data</TD>
* <TD>Actual data of this RR.</TD>
* </TR>
* </TABLE>
*
* @author <A HREF="mailto:sowmya@opennms.org">Sowmya </A>
* @author <A HREF="http://www.opennms.org/">OpenNMS </A>
*
*/
public final class DNSAddressRR {
/**
* <P>
* Name of this RR.
* </P>
*/
private String m_name;
/**
* <P>
* Type of this RR.
* </P>
*/
private int m_type;
/**
* <P>
* Class of this RR.
* </P>
*/
private int m_class;
/**
* <P>
* Time to live for this RR.
* </P>
*/
private long m_TTL;
/**
* <P>
* Time at which this RR was created.
* </P>
*/
private long m_created;
/**
* <P>
* The IP Address for the Route Record.
* </P>
*/
private int[] ipAddress;
/**
* <P>
* Returns the address in the dotted decimal format.
* </P>
*
* @return The address in the dotted decimal format.
*/
private String AddressToByteString() {
return ipAddress[0] + "." + ipAddress[1] + "." + ipAddress[2] + "." + ipAddress[3];
}
/**
* <P>
* Constructs an new DNS Address Resource Record with the specified
* information.
* </P>
*
* @param name
* name of the RR
* @param type
* type of the RR
* @param clas
* class of the RR
* @param ttl
* time for which this RR is valid
* @param dnsIn
* inputstream for this RR
*
* @exception java.io.IOException
* Thrown if an error occurs decoding data from the passed
* DNSInputStream.
*/
public DNSAddressRR(String name, int type, int clas, long ttl, DNSInputStream dnsIn) throws IOException {
m_name = name;
m_type = type;
m_class = clas;
m_TTL = ttl;
m_created = System.currentTimeMillis();
// decode
ipAddress = new int[4];
for (int i = 0; i < 4; ++i) {
ipAddress[i] = dnsIn.readByte();
}
}
/**
* <P>
* Returns the address from the address record as a byte array.
* </P>
*
* @return The address as a byte array.
*/
public byte[] getAddress() {
byte[] ip = new byte[4];
for (int j = 0; j < 4; j++)
ip[j] = (byte) (ipAddress[j]);
return ip;
}
/**
* <P>
* the InetAddress of the address contained for the record.
* </P>
*
* @return The InetAddress of the address
*
* @exception java.net.UnknownHostException
* Thrown if the InetAddress object cannot be constructed.
*/
public InetAddress getInetAddress() throws UnknownHostException {
return InetAddress.getByName(AddressToByteString());
}
/**
* <P>
* Converts the object to a textual string that describes the resource
* record.
* </P>
*
* @return The string describing the object.
*/
public String toString() {
return getRRName() + " Internet Address = " + AddressToByteString();
}
/**
* <P>
* Returns the name of this RR.
* </P>
*
* @return The name of this RR.
*/
public String getRRName() {
return m_name;
}
/**
* <P>
* Returns the type of this RR.
* </P>
*
* @return The type of this RR.
*/
public int getRRType() {
return m_type;
}
/**
* <P>
* Returns the class of this RR.
* </P>
*
* @return The class of this RR.
*/
public int getRRClass() {
return m_class;
}
/**
* <P>
* Returns the TTL of this RR.
* </P>
*
* @return the TTL of this RR
*/
public long getRRTTL() {
return m_TTL;
}
/**
* <P>
* Returns true if still valid i.e. TTL has not expired.
* </P>
*
* @return True if valid, false if not.
*/
public boolean isValid() {
return m_TTL * 1000 > System.currentTimeMillis() - m_created;
}
}