- 先把宏定义添加上去
#ifndef LWIP_DNS
#define LWIP_DNS 1
#endif
-
在系统初始化调用
dns_init();
1、创建一个udp的专用于dns的dns_pcb控制块
2、dns_setserver指定dns的服务器地址写进dns_servers数组 -
在while(1)之前或者在你认为需要调用的地方调用dns_gethostbyname(const char *hostname, ip_addr_t *addr, dns_found_callback found, void *found)
其中,hostname为你需要解析的域名,addr为解析返回的IP地址指针,found回调函数。
=>dns_enqueue将需要dns的域名填充存放在dns_table
这个table的大小就是同时可以dns的域名数量的多少了!
=>dns_check_entry检查dns_table的状态机
=>根据状态机调用dns_send向dns_servers发送数据
=>dns_tmr有个dns定时器不断的dns请求
=>dns_check_entries=>dns_check_entry
最后在dns_recv里收到域名对应的IP
4.特别注意:配置正确的DNS服务器地址。(尽量通过DHCP获取DNS服务器地址,不要手动填写)
/** DNS server IP address /
#ifndef DNS_SERVER_ADDRESS
#define DNS_SERVER_ADDRESS(ipaddr) (ip4_addr_set_u32(ipaddr, ipaddr_addr(“208.67.222.222”))) / resolver1.opendns.com */
#endif
一般程序会将8.8.8.8设置为dns的服务器地址,这是Google提供的免费DNS服务器的IP地址
- 如果没有使用操作系统,需要自己添加定时处理函数,例如在LwIP_Periodic_Handle函数中添加:
#if LWIP_DNS
if (localtime - DNScoarseTimer >= DNS_TMR_INTERVAL)
{
DNScoarseTimer = localtime;
dns_tmr();
}
#endif
dns总结:
static struct dns_table_entry dns_table[DNS_TABLE_SIZE];
这个是用来存需要解析的域名的
DNS_TABLE_SIZE的大小限制域名的个数。
static ip_addr_t dns_servers[DNS_MAX_SERVERS];
DNS_MAX_SERVERS的大小限制了dns服务器地址的个数。
现在把dns_servers一分为二,一分是写死的dns地址,一分就是dhcp得到的dns地址。
将dns_servers大小改为4
#define DNS_MAX_SERVERS 4 // number of DNS servers, default 2
在dhcp_handle_ack函数中将得到的dns从dns_servers[2]开始写入,不然会被后面的手动写入覆盖调。
#if LWIP_DNS
/* DNS servers */
for(n = 0; (n < DNS_MAX_SERVERS-2) && dhcp_option_given(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n); n++) {
ip_addr_t dns_addr;
ip4_addr_set_u32(&dns_addr, htonl(dhcp_get_option_value(dhcp, DHCP_OPTION_IDX_DNS_SERVER + n)));
LWIP_DEBUGF(DHCP_DEBUG | LWIP_DBG_ON, ("dhcp_bind(): DNS: 0x%08"X32_F"\n", ip4_addr_get_u32(&dns_addr)));
dns_setserver(n, &dns_addr);
}
#endif /* LWIP_DNS */
在dns_check_entry函数中,对每个dns server都重复DNS_MAX_RETRIES次数然后切换下一个dns server
if (++pEntry->retries == DNS_MAX_RETRIES)
case DNS_STATE_ASKING: {
if (--pEntry->tmr == 0) {
**if (++pEntry->retries == DNS_MAX_RETRIES)** {
if ((pEntry->numdns+1<DNS_MAX_SERVERS) && !ip_addr_isany(&dns_servers[pEntry->numdns+1])) {
/* change of server */
pEntry->numdns++;
pEntry->tmr = 1;
pEntry->retries = 0;
break;
} else {
LWIP_DEBUGF(DNS_DEBUG, ("dns_check_entry: \"%s\": timeout\n", pEntry->name));
/* call specified callback function if provided */
if (pEntry->found)
(*pEntry->found)(pEntry->name, NULL, pEntry->arg);
/* flush this entry */
pEntry->state = DNS_STATE_UNUSED;
pEntry->found = NULL;
break;
}
}
dhcp_start是DHCP的流程操作的启动开始,与DNS一样都是udp方式的
dhcp_bind提供获得的IP地址,从dhcp_recv函数调用过来的
1.DHCPDISCOVER
2.DHCPOFFER
3.DHCPREQUEST
4.DHCPACK
可以通过dhcp_handle_ack来获取dns服务器地址,而不用手动设置