libevent 自带 dns 解析库,支持同步、异步两种方式解析域名。因 libevent 本身是异步事件驱动型类库,我们在基于它做应用时,也多数是使用异步模型,因此这里介绍一下如何使用 libevent 异步解析域名。 libevent 官网有文章专门介绍 DNS 功能,请参考《Using DNS with Libevent》。
我这里的例子和官网稍有不同,主要体现在对 DNS 服务器的配置上,区分了多平台。因为我发现在 Android (安卓)平台上, libevent 在获取 DNS 服务器时有问题,具体请参考另一篇博文《libevent 在 Android 上的一个改进》。
我使用 libevent-2.1.3-alpha (请到官网下载)和 Qt 5.2 。关于 Qt 环境搭建,参考《Windows下Qt 5.2 for Android开发入门》。
下面是所有代码:
struct event_base * g_evbase = 0;
struct evdns_base * g_dnsbase = 0;
static void _dns_callback(int errcode, struct evutil_addrinfo *addr, void *ptr)
{
if (errcode)
{
printf("%s -> %s\n", (char*)ptr, evutil_gai_strerror(errcode));
}
else
{
struct evutil_addrinfo *ai;
char ip[128];
printf("dns resolved,hostname - %s, ip :\n", (char*)ptr);
for (ai = addr; ai; ai = ai->ai_next)
{
const char *s = NULL;
if (ai->ai_family == AF_INET)
{
struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr;
s = evutil_inet_ntop(AF_INET, &sin->sin_addr, ip, 128);
}
else if (ai->ai_family == AF_INET6)
{
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr;
s = evutil_inet_ntop(AF_INET6, &sin6->sin6_addr, ip, 128);
}
if(s)
{
printf(" %s\n", s);
}
}
}
if(addr)evutil_freeaddrinfo(addr);
}
struct evdns_base * setup_evdns_base(struct event_base *base)
{
if(g_dnsbase)
{
return g_dnsbase;
}
else
{
struct evdns_base * dnsbase = 0;
#if defined(_WIN32)
dnsbase = evdns_base_new(base, 0);
evdns_base_nameserver_ip_add(dnsbase, "8.8.8.8");
#elif defined(ANDROID)
dnsbase = evdns_base_new(base, 0);
{
int ret = 0;
int contains_default = 0;
char buf[PROP_VALUE_MAX];
ret = __system_property_get("net.dns1", buf);
if(ret >= 7)
{
if(!strncmp("8.8.8.8", buf, 7)) contains_default = 1;
evdns_base_nameserver_ip_add(dnsbase, buf);
}
ret = __system_property_get("net.dns2", buf);
if(ret >= 7)
{
if(!strncmp("8.8.8.8", buf, 7)) contains_default = 1;
evdns_base_nameserver_ip_add(dnsbase, buf);
}
if(!contains_default)
{
evdns_base_nameserver_ip_add(dnsbase, "8.8.8.8");
}
}
#else
dnsbase = evdns_base_new(base, 1);
#endif
printf(" dns server count : %d\n", evdns_base_count_nameservers(dnsbase));
g_dnsbase = dnsbase;
return dnsbase;
}
}
static int lookup_host(const char * host)
{
struct evutil_addrinfo hints;
struct evdns_getaddrinfo_request *req;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_flags = EVUTIL_AI_CANONNAME;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
req = evdns_getaddrinfo(g_dnsbase, host, NULL ,
&hints, _dns_callback, (void*)host);
if (req == NULL)
{
printf(" [request for %s returned immediately]\n", host);
return -1;
}
return 0;
}
int main(int argc, char **argv)
{
#ifdef WIN32
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD(2, 2);
(void) WSAStartup(wVersionRequested, &wsaData);
#endif
if(argc < 2)
{
printf("Usage: \n dns_resolv hostname\n");
return 0;
}
g_evbase = event_base_new();
setup_evdns_base(g_evbase);
if(lookup_host(argv[1]) == 0)
{
event_base_loop(g_evbase, EVLOOP_NO_EXIT_ON_EMPTY);
}
event_base_free(g_evbase);
evdns_base_free(g_dnsbase, 1);
#ifdef WIN32
(void) WSACleanup();
#endif
return 0;
}需要说明一点,在我的 Win7 环境下,通过 evdns_base_new(base, 1) 这种方式无法读取到域名服务器,所以我配置了 google 的 8.8.8.8 来使用。
使用libevent异步解析dns,布布扣,bubuko.com
原文:http://blog.csdn.net/foruok/article/details/22738217