一、域名系统
- DNS,Domain Name System,域名系统,是对IP地址和域名进行相互转换的系统,其核心是DNS服务器
- 为什么要提供域名?IP地址难记!域名基本不变,IP相对频繁地改变
- 所有计算机中都记录着默认 DNS 服务器地址,通过这个默认 DNS 服务器得到相应的域名的 IP 地址信息。若该 DNS 服务器无法解析,则会向上级 DNS 服务器询问,逐级上传,最终可能达到顶级 DNS 服务器——根服务器,它知道该向哪个 DNS 服务器询问,向下级 DNS 传递解析请求,得到 IP地址后原路返回,最终将解析的 IP地址传递到发起请求的主机。
- DNS——分布式数据库管理系统
- 查看某个域名的 IP地址:ping www.google.com
- 查看默认 DNS 服务器地址:nslookup(Linux需在执行后再输入server命令)
二、利用域名获取IP地址
1.相关函数
#include<netdb.h>
// 功能:通过域名获取 IP地址等信息
// 返回值:成功时返回 hostent 结构体地址,失败时返回 NULL 指针
struct hostent* gethostbyname(const char* hostname);
struct hostent{
char* h_name; // 官方域名
cahr** h_aliases; // 主页别名(其他域名,一个主页可以有多个域名,同一IP可以绑定多个域名)
int h_addrtype; // 地址族信息(gethostbyname 函数支持 IPv4,IPv6)
h_length; // 保存IP地址长度,IPv4地址为 4,IPv6地址为 16
h_addr_list; // 以整数形式保存域名对应的所有IP地址(用户较多的网站可能分配多个IP给同一个域名,利用多个服务器进行负载均衡)
}
2.演示程序
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<netdb.h>
void error_handling(char* message) {
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
int main(int argc, char* argv[]) {
struct hostent* host;
if (argc != 2) {
printf("Usage: %s <addr> \n", argv[0]);
exit(1);
}
host = gethostbyname(argv[1]);
if (!host)
error_handling("gethost....error");
printf("Official name: %s \n", host->h_name);
for (int i = 0; host->h_aliases[i]; i++) {
printf("Aliases %d: %s \n", i + 1, host->h_aliases[i]);
}
printf("Address type: %s \n", (host->h_addrtype == AF_INET) ? "AF_INET" : "AF_INET6");
for (int i = 0; host->h_addr_list[i]; i++) {
printf("IP addr %d: %s \n", i + 1, inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
}
return 0;
}
三、利用IP地址获取域名
1.相关函数
#include<netdb.h>
// 功能:利用IP地址获取域名相关信息
// 参数:
// addr--含有 IP地址信息的 in_addr 结构体指针,为了同时传递 IPv4地址以外的信息,声明为 char*
// len--向第一个参数传递的地址信息的字节数,IPv4为 4,IPv6为 16
// family--传递地址族信息,IPv4为 AF_INET,IPv6为 AF_INET6
//返回值:成功时返回 hostent 结构体变量的地址,失败时返回 NULL 指针
struct hostent* gethostbyaddr(const char* addr,socklent_t len,int family);
2.演示程序
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
#include<netdb.h>
void error_handling(char* message) {
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
int main(int argc, char* argv[]) {
struct hostent* host;
struct sockaddr_in addr;
if (argc != 2) {
printf("Usage: %s <addr> \n", argv[0]);
exit(1);
}
memset(&addr, 0, sizeof(addr));
addr.sin_addr.s_addr = inet_addr(argv[1]);
host = gethostbyaddr((char*)&addr.sin_addr, 4, AF_INET);
if (!host)
error_handling("gethost....error");
printf("Official name: %s \n", host->h_name);
for (int i = 0; host->h_aliases[i]; i++) {
printf("Aliases %d: %s \n", i + 1, host->h_aliases[i]);
}
printf("Address type: %s \n", (host->h_addrtype == AF_INET) ? "AF_INET" : "AF_INET6");
for (int i = 0; host->h_addr_list[i]; i++) {
printf("IP addr %d: %s \n", i + 1, inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
}
return 0;
}
参考书籍:《TCP/IP网络编程》尹圣雨 著,金果哲 译