If you want to use libevent for a download program on And roid, the domain name resolution problem is involved. It is found that libevent cannot obtain the dns server. I studied the source code and found the problem.
The general process of asynchronous dns resolution using libevent is as follows:
Call evdns_base_new (struct event_base * event_base, int initialize_nameservers) to generate an evdns_base object call evdns_getaddrinfo and provide a callback to parse the processing results in the callback.
Generally, we pass 1 to the second parameter of the evdns_base_new function so that the libevent can initialize nameservers from the system configuration. Read the Registry on windows and/etc/resolv. conf on Linux. The problem is that there is no resolv. conf file on Android, and libevent has not processed it. View the evdns_base_new function implementation in the evdns. c file:
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 WIN32r = evdns_base_config_windows_nameservers(base);#elser = evdns_base_resolv_conf_parse(base, DNS_OPTIONS_ALL, "/etc/resolv.conf");#endifif (r == -1) {evdns_base_free_and_unlock(base, 0);return NULL;}}EVDNS_UNLOCK(base);return base;}
That is, the lines of code # ifdef WIN32.
The solution is to add an ANDROID Macro during compilation and read the dns configuration code for the Android platform. This is explained in my article "Android C language read system attributes. The specific code is as follows:
if (initialize_nameservers) {int r;#ifdef WIN32r = 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"); } }#elser = evdns_base_resolv_conf_parse(base, DNS_OPTIONS_ALL, "/etc/resolv.conf");#endifif (r == -1) {evdns_base_free_and_unlock(base, 0);return NULL;}}
OK. Now it works properly.