第4节 DNS客户端
DNS客户端与DNS(域名服务器)进行通信。DNS系统将域名转换成IP地址。DNS协议是由RFC1035定义的。DNS运行在UDP或TCP之上,使用53号端口。DNS 是无状态协议,所有的信息都包含在一个单一的报文中,在 RFC1035中有该报文的全部文件。DNS报文见表2。
可以通过将ipport.h文件的宏DNS_CLIENT置1来使能DNS客户端。通过每秒调用一次函数dns_check()来更新DNS cashe,从而维持DNS客户端。
DNS客户端在初始化时,必须用DNS服务器的IP地址来填充dns_servers[]数组。dns_servers[]是在 dnsclnt.c 中声明的全局数组。任何未用到的入口参数必须被填充为0。
只要调用一个API函数就可以使用DNS客户端了。某个域名第一次请求转换时,需要使用 dns_query,dns_query_type,或 gethostbyname 等函数。每个函数都是带入域名,返回IP地址到缓存中。只要这个查询被执行过一次,dns_lookup函数就可以从缓存中获取IP地址信息。
4.1 DNS客户端
API int dns_query(char * name, ip_addr * ip_ptr)
● 请求将一个主机名转换为IP地址。
● 参数name为主机名字符串。ip_ptr用来存放可用的IP地址。
● 转换成功返回0,否则返回错误代码。
int dns_query_type(char * name, char type, struct dns_querys ** dns_ptr)
向域名服务器请求一种指定的数据类型。
——类型:DNS_TYPE_QUERY //question 的类型值
DNS_TYPE_IPADDR //Ipv4 地址的类型值
DNS_TYPE_AUTHNS // 权威的域名服务器
DNS_TYPE_ALIAS // 查询域名的别名
void dns_check(void)
必须每秒调用一次来支持DNS超时和重试。
int dns_lookup(ip_addr * ip, char * name)
在DNS缓存中查找域名到IP地址的转换。 如果在缓存中,返回0。
Struct hostent *gethostbyname(char * name )
域名转换的标准 API。成功则返回指向 hostent 结构体的指针,失败则返回NULL。
hostentd的定义在dns.h中。
4.2 DNS应用实例
// url是包含一个完整url的字符串,以NULL结束
// 主机名可以是IP地址,也可以是域名
//实例 75.18.69.29/index.html
// 或www.emgware.com/index.html
//如果字符串中包含IP地址,parse_ipad函数返回0
cp = parse_ipad(&ipaddr, &snbits, (char *)url);
// 是IP地址?
if(cp)
{ // 字符串不是一个IP地址
// 对字符串进行预处理,消除所有的前缀(http//)和域名之后的字符
// 将域名复制到分配的缓冲区
temp_buffer = (unsigned char *)npalloc(strlen((char *)url)+10);
if(temp_buffer)
{
temp_buffer(0) = 0; // in case
//preprocess_url函数只将域名复制到temp_buffer
(void)preprocess_url(temp_buffer, url);
ipaddr = 0;
//试图连上DNS服务器
for(i=0; i<EMG_HTTP_CLIENT_DNS_SEARCH_TIME_SECS; i++)
{
tk_sleep(200);
// 将域名发送给DNS客户端 (www.freescale.com)
test = gethostbyname((char *)temp_buffer);
if(test != NULL)
{
//从DNS返回的IP地址
ulp = (unsigned long *)test->h_addr_list[0);
ipaddr = *ulp;
break;
}
}
npfree(temp_buffer);
if(!ipaddr)
return(EMG_HTTP_CLIENT_CONNECT_ERROR_DNS);
}
else
return(EMG_HTTP_CLIENT_CONNECT_ERROR_ALLOC);
}
表2 DNS报文


可以通过将ipport.h文件的宏DNS_CLIENT置1来使能DNS客户端。通过每秒调用一次函数dns_check()来更新DNS cashe,从而维持DNS客户端。
DNS客户端在初始化时,必须用DNS服务器的IP地址来填充dns_servers[]数组。dns_servers[]是在 dnsclnt.c 中声明的全局数组。任何未用到的入口参数必须被填充为0。
只要调用一个API函数就可以使用DNS客户端了。某个域名第一次请求转换时,需要使用 dns_query,dns_query_type,或 gethostbyname 等函数。每个函数都是带入域名,返回IP地址到缓存中。只要这个查询被执行过一次,dns_lookup函数就可以从缓存中获取IP地址信息。
4.1 DNS客户端
API int dns_query(char * name, ip_addr * ip_ptr)
● 请求将一个主机名转换为IP地址。
● 参数name为主机名字符串。ip_ptr用来存放可用的IP地址。
● 转换成功返回0,否则返回错误代码。
int dns_query_type(char * name, char type, struct dns_querys ** dns_ptr)
向域名服务器请求一种指定的数据类型。
——类型:DNS_TYPE_QUERY //question 的类型值
DNS_TYPE_IPADDR //Ipv4 地址的类型值
DNS_TYPE_AUTHNS // 权威的域名服务器
DNS_TYPE_ALIAS // 查询域名的别名
void dns_check(void)
必须每秒调用一次来支持DNS超时和重试。
int dns_lookup(ip_addr * ip, char * name)
在DNS缓存中查找域名到IP地址的转换。 如果在缓存中,返回0。
Struct hostent *gethostbyname(char * name )
域名转换的标准 API。成功则返回指向 hostent 结构体的指针,失败则返回NULL。
hostentd的定义在dns.h中。
4.2 DNS应用实例
// url是包含一个完整url的字符串,以NULL结束
// 主机名可以是IP地址,也可以是域名
//实例 75.18.69.29/index.html
// 或www.emgware.com/index.html
//如果字符串中包含IP地址,parse_ipad函数返回0
cp = parse_ipad(&ipaddr, &snbits, (char *)url);
// 是IP地址?
if(cp)
{ // 字符串不是一个IP地址
// 对字符串进行预处理,消除所有的前缀(http//)和域名之后的字符
// 将域名复制到分配的缓冲区
temp_buffer = (unsigned char *)npalloc(strlen((char *)url)+10);
if(temp_buffer)
{
temp_buffer(0) = 0; // in case
//preprocess_url函数只将域名复制到temp_buffer
(void)preprocess_url(temp_buffer, url);
ipaddr = 0;
//试图连上DNS服务器
for(i=0; i<EMG_HTTP_CLIENT_DNS_SEARCH_TIME_SECS; i++)
{
tk_sleep(200);
// 将域名发送给DNS客户端 (www.freescale.com)
test = gethostbyname((char *)temp_buffer);
if(test != NULL)
{
//从DNS返回的IP地址
ulp = (unsigned long *)test->h_addr_list[0);
ipaddr = *ulp;
break;
}
}
npfree(temp_buffer);
if(!ipaddr)
return(EMG_HTTP_CLIENT_CONNECT_ERROR_DNS);
}
else
return(EMG_HTTP_CLIENT_CONNECT_ERROR_ALLOC);
}


