diff --git a/example/pom.xml b/example/pom.xml
index 93e5098095..bf318e0cd2 100644
--- a/example/pom.xml
+++ b/example/pom.xml
@@ -108,6 +108,11 @@
netty-codec-haproxy
${project.version}
+
+ ${project.groupId}
+ netty-codec-dns
+ ${project.version}
+
com.google.protobuf
diff --git a/example/src/main/java/io/netty/example/dns/udp/DnsClient.java b/example/src/main/java/io/netty/example/dns/udp/DnsClient.java
new file mode 100644
index 0000000000..7a7381b8b6
--- /dev/null
+++ b/example/src/main/java/io/netty/example/dns/udp/DnsClient.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2020 The Netty Project
+ *
+ * The Netty Project licenses this file to you under the Apache License,
+ * version 2.0 (the "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at:
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+package io.netty.example.dns.udp;
+
+import java.net.InetSocketAddress;
+import java.util.concurrent.TimeUnit;
+
+import io.netty.bootstrap.Bootstrap;
+import io.netty.buffer.ByteBufUtil;
+import io.netty.channel.Channel;
+import io.netty.channel.ChannelHandlerContext;
+import io.netty.channel.ChannelInitializer;
+import io.netty.channel.ChannelPipeline;
+import io.netty.channel.EventLoopGroup;
+import io.netty.channel.SimpleChannelInboundHandler;
+import io.netty.channel.nio.NioEventLoopGroup;
+import io.netty.channel.socket.DatagramChannel;
+import io.netty.channel.socket.nio.NioDatagramChannel;
+import io.netty.handler.codec.dns.DatagramDnsQuery;
+import io.netty.handler.codec.dns.DatagramDnsQueryEncoder;
+import io.netty.handler.codec.dns.DatagramDnsResponse;
+import io.netty.handler.codec.dns.DatagramDnsResponseDecoder;
+import io.netty.handler.codec.dns.DefaultDnsQuestion;
+import io.netty.handler.codec.dns.DnsQuery;
+import io.netty.handler.codec.dns.DnsQuestion;
+import io.netty.handler.codec.dns.DnsRawRecord;
+import io.netty.handler.codec.dns.DnsRecord;
+import io.netty.handler.codec.dns.DnsRecordType;
+import io.netty.handler.codec.dns.DnsSection;
+import io.netty.util.NetUtil;
+
+public final class DnsClient {
+
+ private static final String QUERY_DOMAIN = "www.example.com";
+ private static final int DNS_SERVER_PORT = 53;
+ private static final String DNS_SERVER_HOST = "8.8.8.8";
+
+ private DnsClient() { }
+
+ private static void handleQueryResp(DatagramDnsResponse msg) {
+ if (msg.count(DnsSection.QUESTION) > 0) {
+ DnsQuestion question = msg.recordAt(DnsSection.QUESTION, 0);
+ System.out.printf("name: %s%n", question.name());
+ }
+ for (int i = 0, count = msg.count(DnsSection.ANSWER); i < count; i++) {
+ DnsRecord record = msg.recordAt(DnsSection.ANSWER, i);
+ if (record.type() == DnsRecordType.A) {
+ //just print the IP after query
+ DnsRawRecord raw = (DnsRawRecord) record;
+ System.out.println(NetUtil.bytesToIpAddress(ByteBufUtil.getBytes(raw.content())));
+ }
+ }
+ }
+
+ public static void main(String[] args) throws Exception {
+ InetSocketAddress addr = new InetSocketAddress(DNS_SERVER_HOST, DNS_SERVER_PORT);
+ EventLoopGroup group = new NioEventLoopGroup();
+ try {
+ Bootstrap b = new Bootstrap();
+ b.group(group)
+ .channel(NioDatagramChannel.class)
+ .handler(new ChannelInitializer() {
+ @Override
+ protected void initChannel(DatagramChannel ch) throws Exception {
+ ChannelPipeline p = ch.pipeline();
+ p.addLast(new DatagramDnsQueryEncoder())
+ .addLast(new DatagramDnsResponseDecoder())
+ .addLast(new SimpleChannelInboundHandler() {
+ @Override
+ protected void channelRead0(ChannelHandlerContext ctx, DatagramDnsResponse msg) {
+ try {
+ handleQueryResp(msg);
+ } finally {
+ ctx.close();
+ }
+ }
+ });
+ }
+ });
+ final Channel ch = b.bind(0).sync().channel();
+ DnsQuery query = new DatagramDnsQuery(null, addr, 1).setRecord(
+ DnsSection.QUESTION,
+ new DefaultDnsQuestion(QUERY_DOMAIN, DnsRecordType.A));
+ ch.writeAndFlush(query).sync();
+ boolean succ = ch.closeFuture().await(10, TimeUnit.SECONDS);
+ if (!succ) {
+ System.err.println("dns query timeout!");
+ ch.close().sync();
+ }
+ } finally {
+ group.shutdownGracefully();
+ }
+ }
+}