Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> libevent 在 Android 上的一個改進

libevent 在 Android 上的一個改進

編輯:關於Android編程

想在 And roid 上使用 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 函數實現可知:

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 ,現在可以正常工作了。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved