struct hostent *gethostbyname(const char *name);

gethostbyname函数根据域名解析出服务器的ip地址,它返回一个结构体struct hostent:

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 80int 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转换成sockaddrif (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, 据说迟早要废除,不过目前来说,很多系统都可以看见这两个函数

gethostbyname和struct hostent详解相关推荐

  1. python标准类型内建模块_Python内建模块struct实例详解

    本文研究的主要是Python内建模块struct的相关内容,具体如下. Python中变量的类型只有列表.元祖.字典.集合等高级抽象类型,并没有像c中定义了位.字节.整型等底层初级类型.因为Pytho ...

  2. struct sock详解

    struct sock详解 结构体sock是套接口在网络层的表示,在代码include/net/sock.h 174行定义,下面是其内容:     struct sock {         stru ...

  3. 【C语言】结构体定义 typedef struct 用法详解和用法小结

    结构体定义 typedef struct 用法详解和用法小结 文章目录 结构体定义 typedef struct 用法详解和用法小结 0. 前言 1. 首先:在C中定义一个结构体类型要用typedef ...

  4. c语言struct的作用和用法,c语言struct用法详解

    c语言struct用法详解 在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据.结构体的定义形式为:struct 结构体名{ 结构体所包含的变量或数组 }; 结构体是一种集合,它里面包 ...

  5. python struct.unpack和struct.pack详解

    Python相关文档链接: https://docs.python.org/3/library/struct.html#format-characters 简介 struct模块用于将外部压缩的格式字 ...

  6. C语言struct关键字详解—结构体

    struct 是个神奇的关键字,它将一些相关联的数据打包成一个整体,方便使用. 在网络协议.通信控制.嵌入式系统.驱动开发等地方,我们经常要传送的不是简单的字节流(char 型数组),而是多种数据组合 ...

  7. C/C++语法知识:typedef struct 用法详解

    第一篇:typedef struct与struct的区别 1. 基本解释 typedef为C语言的关键字,作用是为一种数据类型定义一个新名字.这里的数据类型包括内部数据类型(int,char等)和自定 ...

  8. C语言struct用法详解

    数组(Array),它是一组具有相同类型的数据的集合.但在实际的编程过程中,我们往往还需要一组类型不同的数据,例如对于学生信息登记表,姓名为字符串,学号为整数,年龄为整数,所在的学习小组为字符,成绩为 ...

  9. struct ethtool_ops详解

    [get_settings] [set_settings] supported: SUPPORTED_10baseT_Half系列 advertising: ADVERTISED_10baseT_Ha ...

最新文章

  1. explicit关键字
  2. 坚持完成这套学习手册,你就可以去 Google 面试了
  3. 在Linux上搭建 一个简单的vsftpd服务器
  4. UIKit封装的系统动画
  5. java古剑奇谭_古剑奇谭页游源码web可编译的源代码分享价值百万的100%完整源代码...
  6. Redmi K50评测:顶级2K屏加持 无愧全价位焊门员
  7. [Python] set()函数 创建一个无序不重复元素集
  8. 土豆 android 缓存路径,#土豆记事#教你开发Android App之 —— Hello Android
  9. java 弹框_java弹框
  10. 2019美研计算机录取,2019美研录取更新 | 春节OFFER大集锦,没有比OFFER更好的新年礼物了!...
  11. 简单说明经济是什么~
  12. linux中c语言kbhit函数用法,检测按键(Linux中kbhit()函数的实现)
  13. 自己电脑服务器地址的查询办法
  14. kms自动激活Windows和Office
  15. 对于深度与广度的思考
  16. python 识别人名_HanLP中人名识别分析
  17. “大数据杀熟”谁之祸?
  18. Win11插耳机没有声音-个人解决方法分享
  19. 模电学习02:晶体三极管
  20. python高级数据分析_8、Python 数据分析-Pandas高级操作

热门文章

  1. Kubernetes监控体系(12)-alertmanager配置钉钉和邮件告警
  2. golang的ECB加密代码文件下载
  3. 第一次学习Web的总结
  4. 新媒体时代的公关怎么做
  5. How to solve the lossless offline problem of Spring Cloud Alibaba service instance in Kubernetes
  6. 考虑下面特殊的整数线性规划问题max求和 求和 为非负整数
  7. oppo官解root,OPPO官解工具
  8. CentOS Linux虚拟机内存耗费太大
  9. mysql 指定ip段 掩码_网络ip段划分子网掩码
  10. 服务器显示114,DNS设置成114.114.114.114还是自动获取更好?那个网速更快?为什么?...