文章目录
  1. 域名解析
  2. 服务解析
  3. getaddrinfo
  4. getnameinfo

域名解析

Linux提供gethostbyname函数对域名进行解析。

1
2
3
4
5
6
/*
引用方式: #include <netdb.h>
doname: 域名
返回hostent结构体指针: 成功 || 返回NULL并设置h_errno: 失败
*/
struct hostent * gethostbyname(const char * doname);

其中,结构体hostent定义如下。

如果想通过IP地址查到主机信息,使用gethostbyaddr函数。

1
2
3
4
5
6
7
8
/*
引用方式: #include <netdb.h>
addr: 目标主机的IP地址(结构体in_addr或结构体in6_addr的指针)
len: IP地址长度(sizeof(* addr))
type: IP地址类型; AF_INET || AF_INET6
返回hostent结构体指针: 成功 || 返回NULL并设置h_errno: 失败
*/
struct hostent * gethostbyaddr(const void * addr, size_t len, int type);

上述两个函数不可重入。

服务解析

getservbyname函数根据服务名称获取某个服务的完整信息。

1
2
3
4
5
6
7
/*
引用方式: #include <netdb.h>
name: 服务名称
proto: 服务类型; "tcp"表示流服务 || "udp"表示数据报服务 || NULL: 获取所有类型的服务
返回servent结构体指针: 成功 || 返回NULL: 失败
*/
struct servent * getservbyname(const char * name, const char * proto);

其中,结构体servent的定义如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
/*
引用方式: #include <netdb.h>
s_name: 服务名称
s_aliases: 服务别名数组
s_port: 端口号
s_proto: 服务类型
*/
struct servent{
char *s_name;
char **s_aliases;
int s_port;
char *s_proto;
};

也可以通过端口获得服务的完整信息,使用getservbyport函数。

1
2
3
4
5
6
/*
引用方式: #include <netdb.h>
port: 端口号
proto: 服务类型; "tcp"表示流服务 || "udp"表示数据报服务 || NULL: 获取所有类型的服务
*/
struct servent * getservbyport(int port, const char * proto);

上述两个函数不可重入。Linux提供了这些函数可重入版本,在函数名尾部加上_r;

getaddrinfo

getaddrinfo函数既能通过主机名获得IP地址,也能通过服务名获得端口号。

1
2
3
4
5
6
7
8
9
/*
引用方式: #include <netdb.h>
name: 主机名 || 字符串表示的IP地址
service: 服务名 || 端口号
hints: 对输出进行一些控制; 默认设置为NULL
result: result指向一个链表, 用于存储输出结果
返回0: 成功 || 返回错误码: 调用const char * gai_strerror(int ret); 查看具体错误信息
*/
int getaddrinfo(const char * name, const char * service, const struct addrinfo * hints, struct addrinfo * * result);

其中,结构体addrinfo的定义如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
引用方式: #include <netdb.h>
ai_flags: 详见下表
ai_family: 地址族
ai_socktype: 服务类型; SOCK_STREAM || SOCK_DGRAM
ai_protocol: 一般设置为0, 表示使用默认协议
ai_addrlen: socket地址ai_addr的长度
ai_addr: socket地址
ai_canonname: 主机别名
ai_next: 指向下一个结构体addrinfo
*/
struct addrinfo{
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
socklen_t ai_addrlen;
struct sockaddr *ai_addr;
char *ai_canonname;
struct addrinfo *ai_next;
};

 

getaddrinfo将隐式分配堆内存,使用配对函数freeaddrinfo来释放这段内存。

1
2
3
4
/*
引用方式: #include <netdb.h>
*/
void freeaddrinfo(struct addrinfo * result);

getnameinfo

getnameinfo能通过socket地址同时获得以字符串表示的主机名与服务名。

1
2
3
4
5
6
7
8
9
10
/*
引用方式: #include <netdb.h>
host: 存放主机名的地址
hostlen: host这段内存的长度
serv: 存放服务名
servlen: serv这段内存的长度
flags: 详见下表
返回0: 成功 || 返回错误码: 调用const char * gai_strerror(int ret); 查看具体错误信息
*/
int getnameinfo(const struct sockadrr * addr, socklen_t addrlen, char * host, socklen_t hostlen, char * serv, socklen_t servlen, int flags);