在Winsock网络编程中,可以通过主机的IP地址获取主机信息;也可以通过主机名获取主机信息。
1 通过主机IP地址获取主机信息
gethostbyaddr()函数和getnameinfo()函数可以通过主机IP地址获取主机信息。
1.1 gethostbyaddr()函数
该函数的作用是根据网络地址获取主机信息。
1.1.1 函数格式
该函数的格式为
struct hostent* FAR gethostbyaddr(
__in const char* addr,
__in int Len,
__in int type
);
其中,参数addr是主机IP地址;Len是IP地址的长度,单位是字节;type表示地址的类型,该参数的取值可以是AF_INET、AF_INET6和AF_NETBIOS,分别表示IPv4、IPv6和NetBIOS。
如果成功获取了主机信息,则gethostbyaddr()函数返回一个hostent结构的指针,如果失败,则返回一个指向NULL的指针。
1.1.2 hostent结构
hostent结构用来存储主机信息,包括主机名、IPv4地址等。该结构的格式为
typedef struct hostent{
char FAR* h_name;
char FAR h_aliases;
short h_addrtype;
short h_length;
char FAR FAR** h_addr_list;
}HOSTENT, *PHOSTENT, FAR* LPHOSTENT;
其中,成员变量h_name表示主机官方的名字;h_aliases表示主机的别名;h_addrtype返回地址的类型;h_length表示每个地址的长度,单位是字节;h_addr_list主机地址的列表。
1.1.3 相关代码
使用gethostbyaddr()函数和hostent结构获取主机信息的代码如下所示
in_addr addr;
addr.s_addr = inet_addr(“192.168.1.1”);
hostent* info_host = gethostbyaddr((char*)&addr, 4, AF_INET);
需要注意的是,gethostbyaddr()函数的第一个参数不是简单的IP地址字符串,而是将IP地址转换为整形后,再将整形看成字符串。
此时,主机的名字就保存再info_host->h_name中。
1.2 getnameinfo()函数
该函数的作用是将IP地址转换成主机名,并且还可以将端口号转换为服务名。
1.2.1 函数格式
该函数的格式为
int WSAAPI getnameinfo(
__in const struct sockaddr FAR* sa,
__in socklen_t saLen,
__out char FAR* host,
__in DWORD hostLen,
__out char FAR* serv,
__in DWORD servLen,
__in int flags
);
其中,sa是一个指向sockaddr的指针,该指针指向的内容包含了IP地址和端口号;saLen是参数sa的大小,单位是比特;host是转换后的主机名的指针;hostLen指定了参数host的大小,单位是比特;serv是指向转换后的服务名的指针;servLen是参数serv的大小,单位是比特;flags指定了转换的方式。
1.2.2 相关代码
使用getnameinfo()函数获取主机名的相关代码如下所示
char hostname[NI_MAXHOST];
char servInfo[NI_MAXSERV];
struct sockaddr_in saGNI;
saGNI.sin_family = AF_INET;
saGNI.sin_addr.s_addr = inet_addr(“192.168.1.1”);
saGNI.sin_port = htons(80);
getnameinfo(
(struct sockaddr*)&saGNI
, sizeof(struct sockaddr)
, hostname
, NI_MAXHOST
, servInfo
, NI_MAXSERV
, NI_NUMERICSERV
);
其中,NI_MAXHOST和NI_MAXSERV是在WS2tcpip.h中定义的常量,分别表示主机名的最大值和服务名的最大值,其值分别是1025和32。根据IP地址获取到的主机名保存在hostname中,根据端口获取到的服务名保存在servInfo中。NI_NUMERICSERV表示获取到的服务名用端口号代替,如果无法获取到主机名,则用该主机的IP地址代替。
2 通过主机名获取主机信息
gethostbyname()函数和getaddrinfo()函数可以通过主机名获取主机信息。
2.1 gethostbyname()函数
2.1.1 函数格式
gethostbyname()函数的格式为
struct hostent* FAR gethostbyname(
__in const char* name
);
其中,参数name表示主机名。函数的返回值是hostent结构的指针。
2.1.2 相关代码
hostent* info_host = gethostbyaddr(“myhost”);
获取到的主机信息保存在info_host所指向的内存地址中。
2.2 getaddrinfo()函数
2.2.1 函数格式
getaddrinfo()函数的格式为:
INT WSAAPI getaddrinfo(
PCSTR pNodeName
, PCSTR pServiceName
, const ADDRINFOA *pHints
, PADDRINFOA *ppResult
);
其中,参数pNodeName是主机名;pServiceName是服务名或者服务对应的端口号;pHints是addrinfo结构的指针,用来提供支持的套接字类型的一些提示;ppResult是一个指针,该指针指向一个或多个addrinfo结构的链表,这些addrinfo结构包含了要获取的主机信息。如果成功获取了主机信息,则getaddrinfo()函数的返回值是0,否则是非零。
2.2.2 addrinfo结构
该结构用在getaddrinfo()函数中保存主机地址信息,其格式为
typedef struct addrinfo {
int ai_flags;
int ai_family;
int ai_socktype;
int ai_protocol;
size_t ai_addrlen;
char *ai_canonname;
struct sockaddr *ai_addr;
struct addrinfo *ai_next;
} ADDRINFOA, *PADDRINFOA;
其中,ai_flags指定了用在getaddrinfo()函数中的选项;ai_family是地址族;ai_socktype是套接字的类型;ai_protocol是协议类型;ai_addrlen指定了ai_addr指向的内存的大小;ai_canonname指定了主机的正规名字;ai_addr是sockaddr结构的指针,该指针指向的内容为获取到的主机信息;ai_next是一个addrinfo结构的指针,该指针指向的是链表中下一个addrinfo。
2.2.3 相关代码
struct addrinfo hints;
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
struct addrinfo *result = NULL;
getaddrinfo(“myHost”, NULL, &hints, &result);
获取到主机信息保存在result中。