分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.youkuaiyun.com/jiangjunshow
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;}
代码比较简单,从命令行获取待解析域名进行解析。通过 WIN32 ,ANDROID 这样一些宏来区分不同平台。
需要说明一点,在我的 Win7 环境下,通过 evdns_base_new(base, 1) 这种方式无法读取到域名服务器,所以我配置了 google 的 8.8.8.8 来使用。
分享一下我老师大神的人工智能教程。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.youkuaiyun.com/jiangjunshow