`
king_tt
  • 浏览: 2276082 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

使用libevent异步解析dns

 
阅读更多

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 来使用。

分享到:
评论

相关推荐

    libevent 参考手册中文版及源码解析

    6. **源码解析**:深入阅读libevent的源码,可以理解其内部实现细节,如事件调度算法、多线程支持和异步I/O处理等。 7. **性能优化**:libevent提供了很多配置选项来优化性能,例如选择合适的事件模型、使用多线程...

    libevent 2.0.13

    3. **异步DNS解析**:使用libevent的内置功能,无需额外的同步DNS库。 4. **HTTP服务和客户端**:构建基于HTTP的服务器或客户端,进行数据交换。 5. **SSL/TLS支持**:对网络通信进行加密,保证数据传输的安全性。 ...

    异步非阻塞C语言爬虫

    在这个项目中,使用了libevent库来实现异步DNS解析和socket连接。libevent是一个跨平台的事件通知库,它可以监听多个事件源,并在事件发生时调用预先注册的回调函数。libevent支持多种事件模型,包括epoll(Linux下...

    windows下的libevent静态库

    5. **异步DNS解析**:libevent集成了getaddrinfo_a函数,可以在后台异步地执行DNS查找,提高程序响应速度。 **libevent库文件详解:** 1. **libevent.lib**:这是libevent的核心库文件,包含了libevent的基本事件...

    libevent-2.0.22-stable编译好的库

    5. **异步DNS解析**:通过libevent的接口,可以在非阻塞模式下进行DNS查询,这对于网络服务来说非常重要,因为阻塞的DNS查询可能会阻塞整个事件循环。 6. **线程兼容性**:虽然Libevent本身是单线程的,但它可以与...

    libevent(2.1.8)库及头文件文件

    这个库提供了异步网络I/O和时间事件处理的能力,广泛应用于服务器端的开发,如HTTP服务器、DNS解析器等。 描述中提到"libevent的win10(32),android(NDK10),linux(cenots7)",意味着这个库包含了针对三种...

    libevent函数手册

    `libevent`支持异步DNS解析功能,这对于构建高性能网络应用尤其有用。 ```c #include &lt;event2/dns.h&gt; ... struct dns_event *de = dns_get_address(base, "example.com", NULL, NULL, NULL); ``` #### 七、基于...

    libevent的vs工程

    在实际开发中,libevent提供了丰富的API,包括处理TCP/UDP连接、HTTP服务器、DNS解析等。它的`bufferevent`模块则提供了高级的缓冲区管理,使得数据读写更加高效。此外,libevent还支持非阻塞I/O和多路复用技术,如...

    libevent-master.zip

    3. **异步非阻塞 I/O**:libevent 使用异步非阻塞 I/O 模型,避免了在等待 I/O 操作完成时浪费 CPU 时间,提高了系统的并发性能。 4. **操作系统接口适配**:libevent 提供了跨平台的接口,底层根据不同操作系统...

    libevent中文参考手册.zip_libevent_libevent手册_网络编程学习

    此外,libevent还提供了DNS解析功能,可以方便地进行异步DNS查询。 定时事件在libevent中同样重要,我们可以通过event_add函数添加一个定时器,指定超时时间后触发回调函数。这在实现心跳检测、定时任务或者超时...

    Libevent程序员手册(2018版,共18章)

    - **DNS查询**:探讨Libevent如何支持异步DNS查询,以提高网络服务的性能。 4. **高级应用篇** - **多线程支持**:讨论Libevent的多线程模型,以及如何在多线程环境中有效地使用事件库。 - **性能优化**:提供...

    libevent.lib动态库,适合在windows下使用,版本为libevent2.1.8

    在Windows下,libevent的使用有时需要解决一些平台特有问题,比如线程安全、异步DNS解析等。但总体而言,libevent为Windows开发者提供了一个强大且跨平台的事件处理框架,极大地简化了网络编程的复杂性。通过熟练...

    libevent 中文文档.doc

    Libevent 是一个跨平台的异步事件通知库,专为编写高性能、可移植的非阻塞I/O应用而设计。它的主要目标是实现可移植性、速度、可扩展性和易用性。库的核心组成部分包括 evutil、event 和 event_base、bufferevent、...

    libevent-1.3e-Win32

    6. **DNS解析:** 内置的异步DNS解析功能,可以在后台进行域名解析,不阻塞主线程。 **与Memcached的关系** Memcached是分布式内存缓存系统,用于减轻数据库负载,提高应用程序性能。它通过将数据存储在内存中,...

    libevent英文book

    "Ref9_dns.pdf"则涉及到DNS解析,libevent提供了一个简单的API来执行异步DNS查询,这对于网络服务来说是至关重要的。 整体而言,《libevent英文book》涵盖了libevent从基础到高级的所有主题,适合从初学者到高级...

    libevent_源码剖析

    Libevent的核心功能包括事件通知、IO缓存事件、定时器、信号处理、异步DNS解析和HTTP服务器及RPC框架。事件通知允许在文件描述符可读或可写时执行回调函数,IO缓存事件则提供了自动化的读写操作,简化了用户对I/O的...

    libevent对应Android下的库文件

    标题提及的是"libevent对应Android下的库文件",这指的是Libevent,一个开源的、跨平台的事件通知库,用于处理网络和时间触发的异步事件。在Android环境下,由于系统架构和环境的不同,需要对Libevent进行交叉编译,...

    Fast Portable non-blocking network programming with Libevent

    书中还介绍了如何使用Libevent提供的工具函数,以及如何处理TCP连接监听、DNS解析等网络编程相关功能。 5. 代码实例的构建与编辑:文档还提供了如何从书籍的GitHub网站获取代码,将其编译成HTML文档并手工编辑成...

    libevent-2.1.11-stable.rar

    libevent_extras.lib则提供了一些额外的功能,如HTTP服务器、DNS解析和内存池等。 libevent的使用涉及到系统服务和socket编程。在系统服务方面,libevent可以方便地将程序注册为后台服务,使其能在系统启动时自动...

    libevent2.0.21_vs2005

    Libevent 是一个开源的事件通知库,用于编写高性能、异步网络应用程序。它可以帮助开发者处理网络上的连接请求,例如 HTTP、FTP、DNS 等协议,以及套接字(socket)操作。版本号 2.0.21 表示这是该库的一个特定发布...

Global site tag (gtag.js) - Google Analytics