struct hostent *gethostbyname(const char *name);
gethostbyname函数根据域名解析出服务器的ip地址,它返回一个结构体struct hostent:
#include <netdb.h>
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 */
}
#define h_addr h_addr_list[0] /* for backward compatibility */
除了服务器的ip地址外,这个结构体还包含了更多服务器的信息,有:
char *h_name
This is the “official” name of the host.
char **h_aliases
These are alternative names for the host, represented as a null-terminated vector of strings.
主机的可选名字,以NULL做为结束标记
int h_addrtype
This is the host address type; in practice, its value is always either AF_INET or AF_INET6, with the latter being used for IPv6 hosts. In principle other kinds of addresses could be represented in the database as well as Internet addresses; if this were done, you might find a value in this field other than AF_INET or AF_INET6. See Socket Addresses.
int h_length
This is the length, in bytes, of each address.
ip地址的长度,ipv4对应4个字节
char **h_addr_list
This is the vector of addresses for the host. (Recall that the host might be connected to multiple networks and have different addresses on each one.) The vector is terminated by a null pointer.
一般主机可以有多个ip地址,比如www.163.com就有121.14.228.43和121.11.151.72两个ip,h_addr_list就用来
保存多个ip地址
char *h_addr
This is a synonym for h_addr_list[0]; in other words, it is the first host address.
即为h_addr_list[0],表示第一个地址,这个符号其实是兼容老系统而存在的
我们写一个程序来获取主机www.163.com的详细信息:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#define SERVPORT 80
int main(int argc, char **argv)
{
int i, sockfd;
struct hostent *host;
struct sockaddr_in serv_addr;
if ((host = gethostbyname(argv[1])) == NULL) {
printf("gethostbyname error\n");
exit(0);
}
printf("official name: %s\n\n", host->h_name);
printf("address length: %d bytes\n\n", host->h_length);
printf("host name alias: \n");
for (i = 0; host->h_aliases[i]; i++) {
printf("%s\n", host->h_aliases[i]);
}
printf("\naddress list: \n");
for (i = 0; host->h_addr_list[i]; i++) {
if ((sockfd = socket(AF_INET, SOCK_STREAM,0)) == -1) {
printf("socket error\n");
exit(0);
}
// 先清零,然后用struct sockaddr_in来填值
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(SERVPORT);
/* h_addr_list[i]指向in_addr类型 */
serv_addr.sin_addr = *((struct in_addr *)host->h_addr_list[i]);
const char *ip = inet_ntoa(serv_addr.sin_addr);
printf("connect to %s ", ip);
// 系统调用的时候,把sockaddr_in转换成sockaddr
if (connect(sockfd, (struct sockaddr *)&serv_addr, \
sizeof(struct sockaddr)) == -1) {
printf("error\n");
exit(0);
}
printf("success\n");
}
return 0;
}
运行结果如下:
这个程序首先调用gethostbyname得到服务器的各种信息,其中就包含它拥有的ip地址,保存在h_addr_list中,然后
对于h_addr_list中的每个ip地址,都调用connect连接其80端口。h_addr_list保存的ip地址类型是char *,
struct sockaddr_in中sin_addr的类型是struct in_addr,而程序中却直接把h_addr_list[i]强制转换成struct in_addr *
serv_addr.sin_addr = *((struct in_addr *)host->h_addr_list[i]);
这是没有问题的,因为h_addr_list保存的并不是真正的字符串,而是指向struct in_addr类型的指针。
另外,struct in_addr用来表示ip地址,本质上是一个long类型,刚好4个字节。然后我们调用inet_ntoa把它转换
成可读性更强的dots-and-number字符串。关于ip地址和dots-and-number字符串之间的转换有4个函数:
#include <arpa/inet.h>
/* network to ascii */
char *inet_ntoa(struct in_addr in);
/* ascii to network */
int inet_aton(const char *cp, struct in_addr *inp);
const char *inet_ntop(int af, const void *src,
char *dst, socklen_t size);
int inet_pton(int af, const char *src, void *dst); /* presentation format to network */
inet_ntoa和inet_aton不支持ipv6, 据说迟早要废除,不过目前来说,很多系统都可以看见这两个函数
相关推荐
struct hostent *gethostbyname(const char *name); ``` - **参数**: - `name`: 需要解析的域名。 - **返回值**: - 成功:返回指向`hostent`结构体的指针。 - 失败:返回`NULL`。 - **示例代码**: ```c ...
struct hostent *gethostbyname(const char *name); ``` 其中: - `name`: 主机名或域名。 - 返回值:成功时返回一个指向`struct hostent`结构体的指针;失败时返回`NULL`。 `struct hostent`结构体包含以下成员: ...
它返回一个`struct hostent`结构体,包含了关于该主机的IP地址和其他信息。 4. `inet_ntoa()`:将网络字节序的IPv4地址转换为人类可读的点分十进制格式。 5. `WSACleanup()`:当不再需要Winsock服务时,调用此函数...
### C语言之Socket详解 #### 一、基本概念 ##### 1. Domain(协议族) 在C语言中,Socket编程涉及到多个不同的`domain`或称为协议族,它们定义了Socket通信的基本规则。主要的协议族包括: - **AF_UNIX(Unix...
### TCP/IP作业知识点详解 #### 一、作业背景与目的 本次作业主要针对TCP/IP协议栈中的ECHO协议客户端及服务器程序设计,并加入了主机名或IP地址解析功能,旨在加深学生对TCP/IP协议的理解和应用能力。具体目标...
### Windows和Linux获取本机IP地址的通用函数详解 在多平台编程环境下,尤其是涉及到网络通信的应用开发中,能够跨操作系统获取本地IP地址是一项非常实用的功能。本文将深入解析一个适用于Windows与Linux系统的通用...
struct hostent *hp; memset(&sa, 0, sizeof(struct sockaddr_in)); // 清空地址结构体 gethostname(myname, MAXHOSTNAME); // 获取本机主机名 hp = gethostbyname(myname); // 获取本机地址信息 if (hp == ...
struct hostent *gethostbyname(const char *name); ``` #### 十、案例分析 例如,在开发一个简单的Web服务器时,我们可以按照以下步骤进行: 1. 创建Socket。 2. 绑定Socket到一个端口。 3. 进入监听状态。 4. ...
- 然后通过`gethostbyname`函数根据主机名获取主机信息结构体`HOSTENT`。 - 最后,使用`inet_ntoa`函数将结构体中的IP地址转换为字符串形式,并显示出来。 #### 代码详解 接下来,我们将详细分析给定的部分代码...
struct hostent* host_addr = gethostbyname(hostname); ``` 这里 `hostname` 是我们需要访问的服务器域名。 ##### 3.3 创建 Socket 创建一个套接字(Socket)用于通信。这里我们创建了一个 TCP 套接字。 ```cpp ...
struct hostent *pURL = gethostbyname(url); // 准备服务器地址结构 struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_addr.s_addr = *((unsigned long*)pURL->h_addr); addr.sin_port = ...
`gethostbyname()`和`gethostbyaddr()`分别用于通过主机名获取IP地址和通过IP地址获取主机名,它们返回的是`hostent`结构体,其中包含了主机名、别名、地址类型等信息。 总之,Linux网络编程涵盖了从创建套接字、...