手把手教你在netty中使用TCP协议请求DNS服务器( 三 )


这里的encoder是一个DnsQueryEncoder对象 。
看一下它的encoder方法:
void encode(DnsQuery query, ByteBuf out) throws Exception {encodeHeader(query, out);this.encodeQuestions(query, out);this.encodeRecords(query, DnsSection.ADDITIONAL, out);}DnsQueryEncoder会依次编码header、questions和records 。
完成编码之后 , 我们还需要从DNS server的返回中decode出DnsResponse , 这里使用的是netty自带的TcpDnsResponseDecoder:
public final class TcpDnsResponseDecoder extends LengthFieldBasedFrameDecoderTcpDnsResponseDecoder继承自
LengthFieldBasedFrameDecoder , 表示数据是以字段长度来进行分割的 , 这和我们刚刚将的encoder的格式类似 。
来看下他的decode方法:
protected Object decode(ChannelHandlerContext ctx, ByteBuf in) throws Exception {ByteBuf frame = (ByteBuf)super.decode(ctx, in);if (frame == null) {return null;} else {DnsResponse var4;try {var4 = this.responseDecoder.decode(ctx.channel().remoteAddress(), ctx.channel().localAddress(), frame.slice());} finally {frame.release();}return var4;}}decode方法先调用
LengthFieldBasedFrameDecoder的decode方法将要解码的内容提取出来 , 然后调用responseDecoder的decode方法 , 最终返回DnsResponse 。
这里的responseDecoder是一个DnsResponseDecoder 。具体decoder的细节这里就不过多阐述了 。感兴趣的同学可以自行查阅代码文档 。
最后 , 我们得到了DnsResponse对象 。
接下来就是自定义的InboundHandler对消息进行解析了:
class Do53ChannelInboundHandler extends SimpleChannelInboundHandler<DefaultDnsResponse> 在它的channelRead0方法中 , 我们调用了readMsg方法对消息进行处理:
private static void readMsg(DefaultDnsResponse msg) {if (msg.count(DnsSection.QUESTION) > 0) {DnsQuestion question = msg.recordAt(DnsSection.QUESTION, 0);log.info("question is :{}",question);}int i = 0, count = msg.count(DnsSection.ANSWER);while (i < count) {DnsRecord record = msg.recordAt(DnsSection.ANSWER, i);//A记录用来指定主机名或者域名对应的IP地址if (record.type() == DnsRecordType.A) {DnsRawRecord raw = (DnsRawRecord) record;log.info("ip address is: {}",NetUtil.bytesToIpAddress(ByteBufUtil.getBytes(raw.content())));}i++;}}DefaultDnsResponse是DnsResponse的一个实现 , 首先判断msg中的QUESTION个数是否大于零 。
如果大于零 , 则打印出question的信息 。
然后再解析出msg中的ANSWER并打印出来 。
最后 , 我们可能得到这样的输出:
INFOc.f.dnstcp.Do53ChannelInboundHandler - question is :DefaultDnsQuestion(www.flydean.com. IN A)INFOc.f.dnstcp.Do53ChannelInboundHandler - ip address is: 47.107.98.187总结以上就是使用netty创建DNS client进行TCP查询的讲解 。
本文的代码 , 大家可以参考:
learn-netty4


推荐阅读