我正在使用netty开发DNS客户端。 为了测试它,我写了一个简单的带有netty的DNS服务器,它返回了我期待的DnsRecords。
这是我的客户代码:
final NioEventLoopGroup nioEventLoopGroup = new NioEventLoopGroup();
final EventLoop next = nioEventLoopGroup.next();
final DnsNameResolverBuilder dnsNameResolverBuilder = new
DnsNameResolverBuilder(next).channelFactory(new ChannelFactory<DatagramChannel>() {
@Override
public DatagramChannel newChannel() {
return new NioDatagramChannel();
}
}).queryTimeoutMillis(100000).nameServerAddresses(new
DnsServerAddresses() {
@Override
public DnsServerAddressStream stream() {
return new DnsServerAddressStream() {
@Override
public InetSocketAddress next() {
return new InetSocketAddress("127.0.0.1",
TEST_DNS_SD_SERVER_PORT);
}
};
}
});
final DnsNameResolver build = dnsNameResolverBuilder.build();
final DefaultDnsQuestion defaultDnsQuestion = new
DefaultDnsQuestion(TEST_BASE_RECORD_NAME, DnsRecordType.PTR);
build.query(defaultDnsQuestion).addListener(new GenericFutureListener<Future<? super AddressedEnvelope<DnsResponse, InetSocketAddress>>>() {
@Override
public void operationComplete(final Future<? super AddressedEnvelope<DnsResponse, InetSocketAddress>> future) throws Exception {
final AddressedEnvelope<DnsResponse, InetSocketAddress> answer = (AddressedEnvelope<DnsResponse, InetSocketAddress>) future.get();
final DnsResponse content = answer.content();
final int count = content.count(DnsSection.ANSWER);
for (int i = 0; i < count; i++) {
final DnsRecord recordAt = content.recordAt(DnsSection.ANSWER, i);
System.out.println(recordAt);
}
}
}).await();
Thread.sleep(Long.MAX_VALUE);
TEST_BASE_RECORD_NAME
是答案部分中包含3个DnsPtrRecords的记录。
在TEST_DNS_SD_SERVER_PORT
后面我在一个单独的线程中运行DNS服务器,它以下列方式处理请求:
(LocalDNSSDHandler的一部分:)
public void channelRead(final ChannelHandlerContext ctx, final Object msg) {
final DatagramDnsQuery query = (DatagramDnsQuery) msg;
DatagramDnsResponse defaultDnsResponse = null;
try {
final DnsRecord recordAt = query.recordAt(DnsSection.QUESTION);
final Name name = Name.fromString(recordAt.name(), Name.root);
final DnsEntryKey dnsEntryKey =
new DnsEntryKey(name, recordAt.type().intValue());
final List<Record> list =
LocalTestServer.this.getDnsEntries().get(dnsEntryKey);
defaultDnsResponse =
new DatagramDnsResponse(query.recipient(),
query.sender(), query.id());
defaultDnsResponse.addRecord(DnsSection.QUESTION, recordAt);
for (final Record record : list) {
final ByteBuf buffer = ctx.alloc().buffer();
buffer.writeBytes(record.toWireCanonical());
defaultDnsResponse.addRecord(DnsSection.ANSWER, new
DefaultDnsRawRecord(record.getName().toString(),
this.fromRecord(record), Long.MAX_VALUE, buffer));
}
} catch (final Exception e) {
}
ctx.writeAndFlush(defaultDnsResponse);
}
服务器定义ChannelHandler
public void initChannel(final DatagramChannel ch) throws Exception {
ch.pipeline().addLast(new DatagramDnsResponseEncoder());
ch.pipeline().addLast(new DatagramDnsQueryDecoder());
ch.pipeline().addLast(new LocalDNSSDHandler());
}
我在客户端期待的是为我所期待的3个DnsPtrRecords看3 System.out.println
。但我得到的只有1。
当我调试它时,我可以看到,服务器端的编码/解码工作正常。
但是当客户端解码相应的ByteBuf
(其中包含我期望的数据)时,它只返回1个记录,并在代码中跳过另外2个:
(DatagramDnsResponseDecoder)
@Override
protected void decode(ChannelHandlerContext ctx, DatagramPacket packet,
List<Object> out) throws Exception {
final ByteBuf buf = packet.content();
final DnsResponse response = newResponse(packet, buf);
boolean success = false;
try {
final int questionCount = buf.readUnsignedShort();
final int answerCount = buf.readUnsignedShort();
final int authorityRecordCount = buf.readUnsignedShort();
final int additionalRecordCount = buf.readUnsignedShort();
decodeQuestions(response, buf, questionCount);
decodeRecords(response, DnsSection.ANSWER, buf, answerCount);
decodeRecords(response, DnsSection.AUTHORITY, buf,
authorityRecordCount);
decodeRecords(response, DnsSection.ADDITIONAL, buf,
additionalRecordCount);
...//source code of netty 4.1, trimmed
我期待的answerCount
是3。但是什么时候
decodeRecords(response, DnsSection.ANSWER, buf, answerCount);
被调用,它将调用
(DefaultDnsRecordDecoder)
protected DnsRecord decodeRecord(
String name, DnsRecordType type, int dnsClass, long timeToLive,
ByteBuf in, int offset, int length) throws Exception {
if (type == DnsRecordType.PTR) {
in.setIndex(offset, offset + length);
return
new DefaultDnsPtrRecord(name, dnsClass, timeToLive, decodeName0(in));
}
return new DefaultDnsRawRecord(
name, type, dnsClass, timeToLive,
in.retainedDuplicate().setIndex(offset, offset + length));
}
我不明白
in.setIndex(offset, offset + length);
因为它设置了ByteBuf(in)的读写索引,这将跳过Answer部分中的其他DnsRecords,并使其仅返回一个DnsRecord。
我使用的是Netty 4.1.4.Final
答案 0 :(得分:0)
Norman Maurer证实这是一个Bug并在发布中修复它: 4.1.6.Final
谢谢诺曼!