什么是域名

DNS是对IP地址和域名进行互相转换的系统,其核心是DNS服务器。

提供网络服务的服务器端也是通过IP地址区分的,但几乎不可能以非常难记的IP地址形式交换服务器端地址信息。因此,将容易记的域名分配并取代IP地址。

DNS服务器

所有计算机中都记录着默认DNS服务器地址,就是通过这个默认DNS服务器得到相应域名的IP地址信息。在浏览器地址栏中输入域名后,浏览器通过默认DNS服务器获取该域名对应的IP地址,之后才真正进入该网站。

在Linux下可以使用nslookup命令,进一步输入信息,获得默认DNS服务器地址。

计算机内置的默认DNS服务器并不知道网络上所有域名的IP地址信息,此时会向其他DNS服务器询问,并提供给用户。

利用域名获取IP地址

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <netdb.h>

// 成功时返回hostnet结构体地址,失败返回NULL指针
struct hostent* gethostbyname(const char* hostname);

// hostnet 结构体定义
struct hostent {
char* h_name; // official name
char** h_aliases; // alias list
int h_addrtype; // host address type
int h_length; // address length
char** h_addr_list; // address list
};

域名转IP时只需关注h_addr_list

  • h_name:该变量中存有官方域名。官方域名代表某一主页,但实际上,一些公司的域名并未用官方域名注册。
  • h_aliases:可以通过多个域名访问同一主页。同一IP可以绑定多个域名,因此,除官方域名外还可指定其他域名。
  • h_addrtype:gethostbyname函数支持IPv4和IPv6。因此可以通过此变量获取保存在h_addr_list的IP地址的地址族信息。若是IPv4,则此变量存有AF_INET。
  • h_length:保存IP地址长度。IPv4为4字节,IPv6为16字节
  • h_addr_list:通过此变量一整数形式保存域名对应的IP地址。另外,用户较多的网站有可能分配多个IP给同一域名,利用多个服务器进行负载均衡。

利用IP地址获取域名

1
2
3
4
5
6
7
8
#include <netdb.h>

// 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, socklen_t len, int family);

getsockopt & setsockopt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <sys/socket.h>

// sock 用于查看选项套接字文件描述符
// level 要查看的可选项的协议层
// optname 要查看的可选项名
// optval 保存查看结果的缓冲地址值
// optlen 向第四个参数optval传递的缓冲大小。调用该函数后,该变量中保存通过第四个参数返回的 可选项信息的字节数
// 成功返回0,失败返回-1
int getsockopt(int sock, int level, int optname, void* optval, socklen_t optlen);

// sock 用于更改选项套接字文件描述符
// level 要更改的可选项的协议层
// optname 要更改的可选项名
// optval 保存更改结果的缓冲地址值
// optlen 向第四个参数optval传递的可选项信息的字节数
// 成功返回0,失败返回-1
int setsockopt(int sock, int level, int optname, const void* optval, socklen_t optlen);