手把手教你使用netty搭建一个DNS tcp服务器( 二 )


下面是它的decode方法:
    protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {        ByteBuf frame = (ByteBuf)super.decode(ctx, in);        return frame == null ? null : DnsMessageUtil.decodeDnsQuery(this.decoder, frame.slice(), new DnsQueryFactory() {            public DnsQuery newQuery(int id, DnsOpCode dnsOpCode) {                return new DefaultDnsQuery(id, dnsOpCode);            }        });    }decode接受一个ByteBuf对象,首先调用LengthFieldBasedFrameDecoder的decode方法,将真正需要解析的内容解析出来,然后再调用DnsMessageUtil的decodeDnsQuery方法将真正的ByteBuf内容解码成为DnsQuery返回 。
这样就可以在自定义的handler中处理DnsQuery消息了 。
上面代码中,自定义的handler叫做Do53ServerInboundHandler:
class Do53ServerInboundHandler extends SimpleChannelInboundHandler<DnsQuery>从定义看,Do53ServerInboundHandler要处理的消息就是DnsQuery 。
看一下它的channelRead0方法:
    protected void channelRead0(ChannelHandlerContext ctx,                                DnsQuery msg) throws Exception {        DnsQuestion question = msg.recordAt(DnsSection.QUESTION);        log.info("Query is: {}", question);        ctx.writeAndFlush(newResponse(msg, question, 1000, QUERY_RESULT));    }我们从DnsQuery的QUESTION section中拿到DnsQuestion,然后解析DnsQuestion的内容,根据DnsQuestion的内容返回一个response给客户端 。
这里的respone是我们自定义的:
    private DefaultDnsResponse newResponse(DnsQuery query,                                           DnsQuestion question,                                           long ttl, byte[]... addresses) {        DefaultDnsResponse response = new DefaultDnsResponse(query.id());        response.addRecord(DnsSection.QUESTION, question);        for (byte[] address : addresses) {            DefaultDnsRawRecord queryAnswer = new DefaultDnsRawRecord(                    question.name(),                    DnsRecordType.A, ttl, Unpooled.wrappedBuffer(address));            response.addRecord(DnsSection.ANSWER, queryAnswer);        }        return response;    }

经验总结扩展阅读