LV06-03-网络编程-08-域名解析

本文主要是网络编程——域名解析的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
Windows windows11
Ubuntu Ubuntu16.04的64位版本
VMware® Workstation 16 Pro 16.2.3 build-19376536
SecureCRT Version 8.7.2 (x64 build 2214) - 正式版-2020年5月14日
开发板 正点原子 i.MX6ULL Linux阿尔法开发板
uboot NXP官方提供的uboot,NXP提供的版本为uboot-imx-rel_imx_4.1.15_2.1.0_ga(使用的uboot版本为U-Boot 2016.03)
linux内核 linux-4.15(NXP官方提供)
STM32开发板 正点原子战舰V3(STM32F103ZET6)
点击查看本文参考资料
参考方向 参考原文
------
点击查看相关文件下载
--- ---

一、域名解析

前边在学习网络编程的一些基本知识的时候,其实已经了解过域名解析的流程了,所以这里就直接记录在C语言中,有关域名解析的相关API函数。

1. gethostbyname()函数

1.1 函数说明

linux下可以使用man 3 gethostbyname命令查看该函数的帮助手册。

1
2
3
4
5
6
/* 需包含的头文件 */
#include <netdb.h>
extern int h_errno; /* 表示出错号 */

/* 函数声明 */
struct hostent *gethostbyname(const char *name);

【函数说明】该函数可以通过域名获取IP地址。

【函数参数】

  • namechar类型指针变量,表示要转换的域名(其实也可以填一个IP地址)。

【返回值】struct hostent类型结构体指针变量,成功返回一个包含了解析后IP地址的hostent结构体变量的地址,失败返回NULL

【使用格式】none

【注意事项】none

1.2 struct hostent

我们来了解一下上边通过域名获取IP地址的函数的返回值,我们在使用man 3 gethostbyname查看帮助手册的时候,下边有这个结构体说明:

1
2
3
4
5
6
7
8
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 */
}

【成员说明】

  • h_namechar类型指针变量,表示官方域名(Official domain name)。
  • h_aliaseschar类型二级指针真,表示域名的别名,可以通过多个域名访问同一主机。同一 IP 地址可以绑定多个域名,因此除了当前域名还可以指定其他域名。
  • h_addrtypeint类型,gethostbyname() 不仅支持 IPv4,还支持IPv6,可以通过此成员获取IP地址的地址族(地址类型)信息,IPv4 对应 AF_INETIPv6 对应 AF_INET6
  • h_lengthint类型,该成员保存IP地址长度。IPv4 的长度为4个字节,IPv6 的长度为 16 个字节。
  • h_addr_listchar类型二级指针,这是最重要的成员。通过该成员以整数形式保存域名对应的 IP 地址。对于用户较多的服务器,可能会分配多个 IP 地址给同一域名,利用多个服务器进行均衡负载。

【成员结构图】 感觉上边那样写好像不是很明显,可以看一下下边的图:

image-20220704154817867

1.3 使用实例

点击查看实例
test.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <stdio.h>
#include <netdb.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
int i = 0;
if (argc != 2)
{
printf("Use example: %s www.baidu.com\n", argv[0]);
return -1;
}
/* 1.解析域名 */
struct hostent *host;
host = gethostbyname(argv[1]);
if(host == NULL)
{
perror("gethostbyname");
return -1;
}
/* 2.打印别名 */
for(i = 0; host->h_aliases[i]; i++)
{
printf("Aliases %d: %s\n", i+1, host->h_aliases[i]);
}
/* 3.打印地址类型 */
printf("Address type: %s\n", (host->h_addrtype == AF_INET) ? "AF_INET" : "AF_INET6");
/* 4.打印解析出来的IP地址 */
for(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;
}

在终端执行以下命令编译程序:

1
2
gcc test.c -Wall # 生成可执行文件 a.out 
./a.out www.baidu.com # 执行可执行程序

然后,终端会有以下信息显示:

1
2
3
4
Aliases 1: www.baidu.com
Address type: AF_INET
IP addr 1: 39.156.66.18
IP addr 2: 39.156.66.14