libevent 在 Android 上的一个改进
2014-01-06 13:51
323 查看
想在 Android 上使用 libevent 做一个下载程序,牵涉到域名解析的问题,发现 libevent 无法获取到 dns 服务器。研究了一下源码,找到了问题所在。
使用 libevent 的异步 dns 解析的一般过程如下:
调用 evdns_base_new(struct event_base *event_base, int initialize_nameservers) 生成一个 evdns_base 对象
调用 evdns_getaddrinfo 并提供一个回调进行解析
在回调中处理结果
一般我们给 evdns_base_new 函数的第二个参数传递 1 以便 libevent 从系统配置中初始化 nameservers 。在 windows 上读取注册表,在 Linux 上读取 /etc/resolv.conf 。问题就出在这里,Android 上没有 resolv.conf 文件而 libevent 未做处理。查看 evdns.c 文件中的 evdns_base_new 函数实现可知:
就是 #ifdef WIN32 那几行代码。
解决方案是编译时增加一个 ANDROID 宏,针对 Android 平台实现读取 dns 配置的代码,这在我的文章《Android C 语言读取系统属性》中有相关解说。下面是具体的代码:
OK ,现在可以正常工作了。
使用 libevent 的异步 dns 解析的一般过程如下:
调用 evdns_base_new(struct event_base *event_base, int initialize_nameservers) 生成一个 evdns_base 对象
调用 evdns_getaddrinfo 并提供一个回调进行解析
在回调中处理结果
一般我们给 evdns_base_new 函数的第二个参数传递 1 以便 libevent 从系统配置中初始化 nameservers 。在 windows 上读取注册表,在 Linux 上读取 /etc/resolv.conf 。问题就出在这里,Android 上没有 resolv.conf 文件而 libevent 未做处理。查看 evdns.c 文件中的 evdns_base_new 函数实现可知:
struct evdns_base * evdns_base_new(struct event_base *event_base, int initialize_nameservers) { struct evdns_base *base; if (evutil_secure_rng_init() < 0) { log(EVDNS_LOG_WARN, "Unable to seed random number generator; " "DNS can't run."); return NULL; } /* Give the evutil library a hook into its evdns-enabled * functionality. We can't just call evdns_getaddrinfo directly or * else libevent-core will depend on libevent-extras. */ evutil_set_evdns_getaddrinfo_fn(evdns_getaddrinfo); base = mm_malloc(sizeof(struct evdns_base)); if (base == NULL) return (NULL); memset(base, 0, sizeof(struct evdns_base)); base->req_waiting_head = NULL; EVTHREAD_ALLOC_LOCK(base->lock, EVTHREAD_LOCKTYPE_RECURSIVE); EVDNS_LOCK(base); /* Set max requests inflight and allocate req_heads. */ base->req_heads = NULL; evdns_base_set_max_requests_inflight(base, 64); base->server_head = NULL; base->event_base = event_base; base->global_good_nameservers = base->global_requests_inflight = base->global_requests_waiting = 0; base->global_timeout.tv_sec = 5; base->global_timeout.tv_usec = 0; base->global_max_reissues = 1; base->global_max_retransmits = 3; base->global_max_nameserver_timeout = 3; base->global_search_state = NULL; base->global_randomize_case = 1; base->global_getaddrinfo_allow_skew.tv_sec = 3; base->global_getaddrinfo_allow_skew.tv_usec = 0; base->global_nameserver_probe_initial_timeout.tv_sec = 10; base->global_nameserver_probe_initial_timeout.tv_usec = 0; TAILQ_INIT(&base->hostsdb); if (initialize_nameservers) { int r; #ifdef WIN32 r = evdns_base_config_windows_nameservers(base); #else r = evdns_base_resolv_conf_parse(base, DNS_OPTIONS_ALL, "/etc/resolv.conf"); #endif if (r == -1) { evdns_base_free_and_unlock(base, 0); return NULL; } } EVDNS_UNLOCK(base); return base; }
就是 #ifdef WIN32 那几行代码。
解决方案是编译时增加一个 ANDROID 宏,针对 Android 平台实现读取 dns 配置的代码,这在我的文章《Android C 语言读取系统属性》中有相关解说。下面是具体的代码:
if (initialize_nameservers) { int r; #ifdef WIN32 r = evdns_base_config_windows_nameservers(base); #elif defined(ANDROID) { int add_servers = 0; char buf[PROP_VALUE_MAX]; r = __system_property_get("net.dns1", buf); if(r >= 7) { add_servers++; evdns_base_nameserver_ip_add(base, buf); } r = __system_property_get("net.dns2", buf); if(r >= 7) { add_servers++; evdns_base_nameserver_ip_add(base, buf); } if(add_servers == 0) { evdns_base_nameserver_ip_add(base,"8.8.8.8"); } } #else r = evdns_base_resolv_conf_parse(base, DNS_OPTIONS_ALL, "/etc/resolv.conf"); #endif if (r == -1) { evdns_base_free_and_unlock(base, 0); return NULL; } }
OK ,现在可以正常工作了。
相关文章推荐
- Android Hook Java的的一个改进版本
- Android 一个改进的okHttp封装库
- Android 4.4对VSync机制的一个改进
- Android一个自定义的工具条(ViewPager+GridView)(还在改进中~)
- 贡献一个Android系统中DS18B20驱动程序,希望对大家有帮助
- 一个帖子学会Android开发四大组件
- Android编程心得-设计一个可重用的自定义Dialog
- Android tablet Fragment 中 TableLayout的同一行相邻的两个单元格合并成一个单元格显示?
- Android 在同一个手机上安装多个同样的apk,便于调试
- Androidpn 一个实现 android 推送服务的开源项目
- Android自定义View画出一个时钟(时针、分针、秒针)完美搭配当前时间走动
- 定制一个Android的Launcher(Home)
- Android开发之旅一PopupWindow写的一个基类和PopupWindow中EditText输入法的问题
- android 欢迎界面的实现在一个activity中
- Android 图片如何高效加载与缓存 —— (3) 改进和增加功能
- Android 自定义一个好看的dialog,并实现水波纹特效(兼容低版本)
- 定制你自己的android手机桌面Launcher===一个完成Launcher开发的介绍-第二篇
- 扩展 自定义 LinearLayout 自定义的一个网址http://www.eoeandroid.com/thread-19388-1-1.html
- Android Fragment——添加一个没有UI的Fragment