最近在优化一个监控模块里面的dns解析功能,原来的做法是用旁路线程调用getaddrinfo去同步解析,解析实时性非常差,所以决定将解析改成异步执行。网上搜索了一些dns异步解析的库/接口, 大致有:getaddrinfo_a 、adns、c-ares、udns等等。这些库虽然功能相对比较全,但是在我的场景各种别扭或者低效,不能很好地满足我的需求:其实很简单,我就需要解析ipv4的协议编解码接口就行了,然后结合epoll完成异步解析。在纠结了很久之后,决定按照dns协议自己实现解析ipv4的协议编解码接口,其实就实现了2个接口: IPv4ReqPack、IPv4RspUnpack。
【头文件】
/// dns协议打包解包(ipv4地址)
/// @file
/// @date 2014-08-29 22:13:30
/// @version 1.0.0
/// @author Zhou Ling(周龄), zhou.0@foxmail.com
/// @namespace hydra
#ifndef __DNS_PACKER_H__
#define __DNS_PACKER_H__ \
"$Id: dns_packer.h 2207 2014-09-02 04:32:47Z zhouling $"
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <endian.h>
#include <netinet/in.h>
#include <vector>
namespace hydra {
const short DNS_ERR_BAD_DOMAIN = 32767;
const short DNS_ERR_BAD_BUFFER = 32766;
const short DNS_ERR_NULL_CNT = 32765;
const short DNS_ERR_BAD_ID = 32764;
const short DNS_ERR_UNPACK = 32763;
const short DNS_ERR_TIMEOUT = 32762;
/// @attention 要特别注意字节序
struct DnsHeader
{
uint16_t id; // bits: 0-15; Identification
union // bits: 16-31; Flag
{
struct // 这个结构体的定义是为了方便操作具体的bit fields
{
#if __BYTE_ORDER == __LITTLE_ENDIAN
uint8_t rd : 1; // bit: 23; Recursion Desired
uint8_t tc : 1; // bit: 22; Truncated
uint8_t aa : 1; // bit: 21; Authoritative Answer
uint8_t opcode : 4; // bits: 17,18,19,20; Operation Code
uint8_t qr : 1; // bit: 16; Query/Response
uint8_t rcode : 4; // bits: 28,29,30,31; Return Code
uint8_t cd : 1; // bit: 27; Checking Disabled
uint8_t ad : 1; // bit: 26; Authenticated Data
uint8_t z : 1; // bit: 25; Zero, Reserved
uint8_t ra : 1; // bit: 24; Recursion Available
#else
uint8_t qr : 1; // bit: 16; Query/Response
uint8_t opcode : 4; // bits: 17,18,19,20; Operation Code
uint8_t aa : 1; // bit: 21; Authoritative Answer
uint8_t tc : 1; // bit: 22; Truncated
uint8_t rd : 1; // bit: 23; Recursion Desired
uint8_t ra : 1; // bit: 24; Recursion Available
uint8_t z : 1; // bit: 25; Zero, Reserved
uint8_t ad : 1; // bit: 26; Authenticated Data
uint8_t cd : 1; // bit: 27; Checking Disabled
uint8_t rcode : 4; // bits: 28,29,30,31