DEV Community

Salad Lam
Salad Lam

Posted on

netty5: UDP DNS client example (1)

io.netty5.example.dns.udp.DnsClient is DNS client to lookup A record of domain "www.example.com" by UDP.

Setup io.netty5.channel.Channel instance

Please read the following code.

EventLoopGroup group = new MultithreadEventLoopGroup(NioHandler.newFactory())
Bootstrap b = new Bootstrap();
b.group(group)
 .channel(NioDatagramChannel.class)
 .handler(new ChannelInitializer<DatagramChannel>() {
     @Override
     protected void initChannel(DatagramChannel ch) {
         ChannelPipeline p = ch.pipeline();
         p.addLast(new DatagramDnsQueryEncoder())
         .addLast(new DatagramDnsResponseDecoder())
         .addLast(new SimpleChannelInboundHandler<DatagramDnsResponse>() {
            @Override
            protected void messageReceived(ChannelHandlerContext ctx, DatagramDnsResponse msg) {
                try {
                    handleQueryResp(msg);
                } finally {
                    ctx.close();
                }
            }
        });
     }
 });
Enter fullscreen mode Exit fullscreen mode
  1. anything related to communication is executed in one of the threads of EventLoopGroup
  2. NioDatagramChannel.class states that the underlying network library is Java NIO DatagramChannel
  3. handler() accepts a subclass of io.netty5.channel.ChannelInitializer which implements the function initChannel(DatagramChannel). It is to setup list of ChannelHandler in ChannelPipeline. I called this class setup channel class

Channel instances will be built and obtained in the following.

final Channel ch = b.bind(0).asStage().get();
Enter fullscreen mode Exit fullscreen mode

When bind(0) is called, io.netty5.bootstrap.Bootstrap#init is triggered.

@Override
Future<Channel> init(Channel channel) {
    ChannelPipeline p = channel.pipeline();

    setChannelOptions(channel, newOptionsArray(), logger);
    setAttributes(channel, newAttributesArray());

    p.addLast(config.handler());

    return channel.executor().newSucceededFuture(channel);
}
Enter fullscreen mode Exit fullscreen mode

Value of config.handler() is setup channel class. And then io.netty5.channel.ChannelInitializer#handlerAdded is triggered.

@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
    try {
        initChannel((C) ctx.channel());
    } catch (Throwable cause) {
        // Explicitly call exceptionCaught(...) as we removed the handler before calling initChannel(...).
        // We do so to prevent multiple calls to initChannel(...).
        channelExceptionCaught(ctx, cause);
    } finally {
        if (!ctx.isRemoved()) {
            ctx.pipeline().remove(this);
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Setup channel class will be removed after ChannelPipeline is setup. Then the following will be in ChannelPipeline

  • DefaultChannelPipeline$HeadHandler
  • DatagramDnsQueryEncoder
  • DatagramDnsResponseDecoder
  • subclass of SimpleChannelInboundHandler
  • DefaultChannelPipeline$TailHandler

Top comments (0)