在实现TCP/UDP编程的时候,服务端绑定的IP地址是点分十进制的,如124.222.215.205,如果提供的是域名,此时我们需要将域名转换成点分十进制的IP地址,这个过程就是 “ 域名解析 ”,实现域名转换的函数就是 gethostbyname。
目录
1、gethostbyname
2、hostent结构体成员 h_addr_list
3、使用 gethostbyname 函数解析域名
(1) 获取到主机相关信息
(2) 将主机结构体信息中的网络字节序IP转换成本地字节序IP
(3) 完整代码
1、gethostbyname
gethostbyname 函数的作用是获取主机的相关信息,这里的相关信息就包含主机的IP地址。我们需要重点了解的是这个函数的返回值。
参数name:输入域名或者IP地址
返回值:失败返回NULL,同时 h_errno 会被设置,注意普通函数报错设置的是errno,gethostbyname 函数出错设置的是herror,我们可以通过 hstrerror 函数来获取h_errno对应的错误信息。
成功返回一个结构体,主机的IP地址就放在最后一个参数 h_addr_list 中,h_addr_list 中存放的IP地址是32位网络字节序的整数。
struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char **h_addr_list; /* list of addresses */
}
2、hostent结构体成员 h_addr_list
你或许会觉得好奇,为什么输入一个域名会得到一个IP地址列表?一个域名可能只是一个服务器集群的入口,这里得到的IP地址列表,其实是一个集群中不同服务器的虚拟IP。
为了便于向后兼容,Linux系统将IP地址列表中的第一个地址定义成宏 h_addr,在使用时我们可以直接获取 h_addr 的值来作为解析后的结果,注意,这里的 h_addr 也是32位网络字节序。
3、使用 gethostbyname 函数解析域名
下面就使用 gethostbyname 函数来解析百度域名(www.baidu.com)
(1) 获取到主机相关信息
struct hostent* hs = gethostbyname("www.baidu.com");
if(hs == NULL)
{
herror("gethostbyname");
return 1;
}
(2) 将主机结构体信息中的网络字节序IP转换成本地字节序IP
struct in_addr in;
in.s_addr =*((uint32_t*)hs->h_addr_list[0]);
char* addr = inet_ntoa(in); // 网络字节序转本地字节序
(3) 完整代码
#include <stdio.h>
#include <netdb.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(){
// 解析域名,获取到主机信息
struct hostent* hs = gethostbyname("www.baidu.com");
if(hs == NULL)
{
herror("gethostbyname");
return 1;
}
struct in_addr in;
in.s_addr =*((uint32_t*)hs->h_addr_list[0]);
// 将主机信息中的网络字节序IP转换成本地字节序IP
char* addr = inet_ntoa(in);
printf("%s\n", addr);
return 0;
}