说明:
本节主要记录三个名词:DNS、域名及IP。
IP地址:网络层的主机地址。老生常谈啦。
目前分为IPV4和IPV6。
如百度的地址之一:202.108.22.5
域名就是IP的别名吧,因为人类对数字的记忆较难,所以把某个IP起个别名。
如百度的域名:www.baidu.com
在浏览器地址栏中输入其域名就可以访问到百度的服务器,不用记其IP地址了。
DNS 是对IP地址和域名进行相互转换的系统,其核心是 DNS 服务器。
因为 TCP/IP 协议栈中网络层需要的是 IP 地址,而不是域名,所以得需要把域名转换成对于的IP地址。
如图:
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 from name server. */ }; /* 成功时返回 hostent 结构体地址,失败时返回 NULL 指针 */ #include <netdb.h> struct hostent *gethostbyname(const char *hostname);
struct hostent
:
/* addr: 含有IP地址信息的 in_addr 结构体指针。为了同时传递 IPV4 地址之外的全部信息,该变量的类型声明为 char 指针 len: 向第一个参数传递的地址信息的字节数,IPV4时为 4 ,IPV6 时为16. family: 传递地址族信息,ipv4 是 AF_INET ,IPV6是 AF_INET6 成功时返回 hostent 结构体变量地址值,失败时返回 NULL 指针 */ #include <netdb.h> struct hostent *gethostbyaddr(const char *addr, socklen_t len, int family);
getaddrinfo()
能够处理 域名到IP 和 服务到端口 这两种转换。可重入的。
getnameinfo()
能够处理 IP到域名 和 端口到服务 这两种转换。可重入的。
#include <sys/socket.h> #include <netdb.h> int getaddrinfo(const char *restrict nodename, /* host 或者IP地址 */ const char *restrict servname, /* 十进制端口号 或者常用服务名称如"ftp"、"http"等 */ const struct addrinfo *restrict hints, /* 获取信息要求设置 */ struct addrinfo **restrict res); /* 获取信息结果 */ void freeaddrinfo(struct addrinfo *ai); // 需要了解的结构体 struct addrinfo { int ai_flags; /* 附加选项,多个选项可以使用或操作结合 */ int ai_family; /* 指定返回地址的协议簇,取值范围:AF_INET(IPv4)、AF_INET6(IPv6)、AF_UNSPEC(IPv4 and IPv6) */ int ai_socktype; /* enum __socket_type 类型,设置为0表示任意类型 */ int ai_protocol; /* 协议类型,设置为0表示任意类型 */ socklen_t ai_addrlen; /* socket address 的长度 */ struct sockaddr *ai_addr; /* socket address 的地址 */ char *ai_canonname; /* Canonical name of service location. */ struct addrinfo *ai_next; /* 指向下一条信息,因为可能返回多个地址 */ }; // The sockaddr structure is used to define a socket address which is used in the bind(), connect(), getpeername(), getsockname(), recvfrom(), and sendto() functions. struct sockaddr { sa_family_t sa_family; //Address family. char sa_data[14]; // Socket address (variable-length data). }; // 该结构体一般都会转为 struct sockaddr_in { sa_family_t sin_family; //地址族(Address Family) uint16_t sin_port; //16 位 TCP/UDP 端口号 struct in_addr sin_addr; //32位 IP 地址 char sin_zero[8]; //为了保证其大小一致,目前不使用 }; struct in_addr { in_addr_t s_addr; //32位IPV4地址 }
getaddrinfo()
参数说明:
struct addrinfo
结构体。
struct addrinfo
结构体列表,使用完成后调用 freeaddrinfo()
释放存储结果空间。getnameinfo()
能够处理 IP到域名 和 端口到服务 这两种转换。可重入的。
#include <netdb.h> /** * @param addr,输入参数。struct addrinfo中的struct sockaddr * @param addrlen,输入参数。struct addrinfo中的socklen_t * @param host,输出参数。IP地址 * @param hostlen,输入参数。告诉函数host的大小 * @param serv,输出参数。端口号 * @param servlen,输入参数。告诉函数servlen的大小 * @param flags,输入参数。告诉函数struct sockaddr的处理方式 * * @return 返回零则成功。 */ int getnameinfo(const struct sockaddr *sockaddr, socklen_t addrlen, char *host, size_t hostlen, char *serv, size_t servlen, int flags);
DNS主要基于UDP。
目前全球只有13台域名根服务器。
并不是每条DNS查询都要到达根服务器的,查询是逐级查询,各级都有缓存表,先查缓存表中的,没有再往上报。
8.8.8.8是Google公司提供的免费DNS服务器的IP地址。
也可以指定本地的DNS服务器,只要能解析域名与IP即可。
- DNS 原理入门
- 网络相关结构体参考
- getaddrinfo