Java向dns服务器发送udp数据包

Java向dns服务器发送udp数据包,java,dns,udp,client,Java,Dns,Udp,Client,我正在尝试将udp数据包发送到指定的dns服务器,并从dns服务器接收响应 问题是我没有得到服务器的响应。我试图用客户端套接字接收数据包,但没有成功 正在寻求帮助以解决此问题 这是我的UdpClient.java import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio

我正在尝试将udp数据包发送到指定的dns服务器,并从dns服务器接收响应

问题是我没有得到服务器的响应。我试图用客户端套接字接收数据包,但没有成功

正在寻求帮助以解决此问题

这是我的UdpClient.java

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;

class UdpClient
{
    public static void main (String args[]) throws Exception
    {
        Scanner scan = new Scanner(System.in);
        System.out.print("Enter a hostname: ");
        // host name
        String hostname = scan.next();
        // socket
        DatagramSocket clientSocket = new DatagramSocket();
        InetAddress ipAddress = InetAddress.getByName(hostname);
        String message = "0471001000000";
        byte[] data = message.getBytes(StandardCharsets.UTF_8);

        // datagram packet
        DatagramPacket sendPacket = new DatagramPacket(data, data.length, ipAddress, 53);
        // send the packet
        clientSocket.send(sendPacket);
        // set a receive timeout, 2000 milliseconds
        // packet for receive
        byte[] rdata = new byte[1024];
        DatagramPacket receivePacket = new DatagramPacket(rdata, rdata.length, ipAddress, 53);
        // wait for a response from the server
        clientSocket.receive(receivePacket);
        System.out.println("Host Name: " + ipAddress.getHostName());
        System.out.println("Canonical Host Name: " + ipAddress.getCanonicalHostName());
        System.out.println("Local Host: " + ipAddress.getLocalHost());
        System.out.println("Loopback Address: " + ipAddress.getLoopbackAddress());
        System.out.println("IPv4: " + ipAddress.getHostAddress());
        String serverMessage = new String(receivePacket.getData(), 0, receivePacket.getLength());
        System.out.println("FROM SERVER: " + serverMessage);
    }
}

下面是一个通过UDP查询DNS记录并打印结果的快速脏示例:

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/**
 * A quick and dirty example of query DNS A record and log response.
 * This code has no error handling.
 *
 */

public class DNSClient {
    private static final String DNS_SERVER_ADDRESS = "8.8.8.8";
    private static final int DNS_SERVER_PORT = 53;

    public static void main(String[] args) throws IOException {
        String domain = "google.com";
        InetAddress ipAddress = InetAddress.getByName(DNS_SERVER_ADDRESS);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        DataOutputStream dos = new DataOutputStream(baos);

        // *** Build a DNS Request Frame ****

        // Identifier: A 16-bit identification field generated by the device that creates the DNS query. 
        // It is copied by the server into the response, so it can be used by that device to match that 
        // query to the corresponding reply received from a DNS server. This is used in a manner similar 
        // to how the Identifier field is used in many of the ICMP message types.
        dos.writeShort(0x1234);

        // Write Query Flags
        dos.writeShort(0x0100);

        // Question Count: Specifies the number of questions in the Question section of the message.
        dos.writeShort(0x0001);

        // Answer Record Count: Specifies the number of resource records in the Answer section of the message.
        dos.writeShort(0x0000);

        // Authority Record Count: Specifies the number of resource records in the Authority section of 
        // the message. (“NS” stands for “name server”)
        dos.writeShort(0x0000);

        // Additional Record Count: Specifies the number of resource records in the Additional section of the message.
        dos.writeShort(0x0000);

        String[] domainParts = domain.split("\\.");
        System.out.println(domain + " has " + domainParts.length + " parts");

        for (int i = 0; i<domainParts.length; i++) {
            System.out.println("Writing: " + domainParts[i]);
            byte[] domainBytes = domainParts[i].getBytes("UTF-8");
            dos.writeByte(domainBytes.length);
            dos.write(domainBytes);
        }

        // No more parts
        dos.writeByte(0x00);

        // Type 0x01 = A (Host Request)
        dos.writeShort(0x0001);

        // Class 0x01 = IN
        dos.writeShort(0x0001);

        byte[] dnsFrame = baos.toByteArray();

        System.out.println("Sending: " + dnsFrame.length + " bytes");
        for (int i =0; i< dnsFrame.length; i++) {
            System.out.print("0x" + String.format("%x", dnsFrame[i]) + " " );
        }

        // *** Send DNS Request Frame ***
        DatagramSocket socket = new DatagramSocket();
        DatagramPacket dnsReqPacket = new DatagramPacket(dnsFrame, dnsFrame.length, ipAddress, DNS_SERVER_PORT);
        socket.send(dnsReqPacket);

        // Await response from DNS server
        byte[] buf = new byte[1024];
        DatagramPacket packet = new DatagramPacket(buf, buf.length);
        socket.receive(packet);

        System.out.println("\n\nReceived: " + packet.getLength() + " bytes");

        for (int i = 0; i < packet.getLength(); i++) {
            System.out.print(" 0x" + String.format("%x", buf[i]) + " " );
        }
        System.out.println("\n");


        DataInputStream din = new DataInputStream(new ByteArrayInputStream(buf));
        System.out.println("Transaction ID: 0x" + String.format("%x", din.readShort()));
        System.out.println("Flags: 0x" + String.format("%x", din.readShort()));
        System.out.println("Questions: 0x" + String.format("%x", din.readShort()));
        System.out.println("Answers RRs: 0x" + String.format("%x", din.readShort()));
        System.out.println("Authority RRs: 0x" + String.format("%x", din.readShort()));
        System.out.println("Additional RRs: 0x" + String.format("%x", din.readShort()));

        int recLen = 0;
        while ((recLen = din.readByte()) > 0) {
            byte[] record = new byte[recLen];

            for (int i = 0; i < recLen; i++) {
                record[i] = din.readByte();
            }

            System.out.println("Record: " + new String(record, "UTF-8"));
        }

        System.out.println("Record Type: 0x" + String.format("%x", din.readShort()));
        System.out.println("Class: 0x" + String.format("%x", din.readShort()));

        System.out.println("Field: 0x" + String.format("%x", din.readShort()));
        System.out.println("Type: 0x" + String.format("%x", din.readShort()));
        System.out.println("Class: 0x" + String.format("%x", din.readShort()));
        System.out.println("TTL: 0x" + String.format("%x", din.readInt()));

        short addrLen = din.readShort();
        System.out.println("Len: 0x" + String.format("%x", addrLen));

        System.out.print("Address: ");
        for (int i = 0; i < addrLen; i++ ) {
            System.out.print("" + String.format("%d", (din.readByte() & 0xFF)) + ".");
        }
    }

}
import java.io.ByteArrayInputStream;
导入java.io.ByteArrayOutputStream;
导入java.io.DataInputStream;
导入java.io.DataOutputStream;
导入java.io.IOException;
导入java.net.DatagramPacket;
导入java.net.DatagramSocket;
导入java.net.InetAddress;
/**
*DNS查询记录和日志响应的一个快速而肮脏的示例。
*此代码没有错误处理。
*
*/
公共类DNSClient{
私有静态最终字符串DNS\u服务器\u地址=“8.8.8.8”;
专用静态最终int DNS_服务器_端口=53;
公共静态void main(字符串[]args)引发IOException{
String domain=“google.com”;
InetAddress ipAddress=InetAddress.getByName(DNS\u服务器\u地址);
ByteArrayOutputStream bas=新的ByteArrayOutputStream();
DataOutputStream dos=新的DataOutputStream(BAS);
//***构建DNS请求框架****
//标识符:由创建DNS查询的设备生成的16位标识字段。
//它被服务器复制到响应中,因此该设备可以使用它来匹配该响应
//查询从DNS服务器收到的相应回复。其使用方式类似
//了解标识符字段在许多ICMP消息类型中的使用方式。
dos.writeShort(0x1234);
//写入查询标志
dos.writeShort(0x0100);
//问题计数:指定消息的问题部分中的问题数。
dos.writeShort(0x0001);
//应答记录计数:指定消息应答部分中的资源记录数。
dos.writeShort(0x0000);
//权限记录计数:指定的权限部分中的资源记录数
//消息。(“NS”代表“名称服务器”)
dos.writeShort(0x0000);
//附加记录计数:指定消息附加部分中的资源记录数。
dos.writeShort(0x0000);
字符串[]domainParts=domain.split(“\\”);
System.out.println(domain+“has”+domainParts.length+“parts”);
对于(int i=0;i 0){
字节[]记录=新字节[recLen];
对于(int i=0;i
您是否验证了服务器正在接收数据包?如何验证?例如,当我输入“google.com”时,程序正在clientSocket.receive(reicePacket)行等待,什么也不做。我的错误。我假设它是本地服务器。远程名称服务器希望您向其发送DNS wireformat。Java不是我的语言,但看起来你没有这么做。因此,我的猜测是,您的UDP数据包可以很好地到达服务器,但服务器会考虑其不可解析的垃圾并忽略它。@paulusaleksiūnas我认为我下面的答案应该是可以接受的答案。