目录

定义

相关方法

1. getaddrinfo(const char, const char, const struct addrinfo, struct addrinfo*)

2. freeaddrinfo(struct addrinfo*)

3. 拷贝addrinfo结构


定义

addrinfo结构主要在网络编程解析hostname时使用,其在头文件#include<netdb.h>中,定义如下:

struct addrinfo {int ai_flags;   /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */int ai_family;  /* PF_xxx */int ai_socktype;    /* SOCK_xxx */int ai_protocol;    /* 0 or IPPROTO_xxx for IPv4 and IPv6 */socklen_t ai_addrlen;   /* length of ai_addr */char    *ai_canonname;  /* canonical name for hostname */struct  sockaddr *ai_addr;  /* binary address */struct  addrinfo *ai_next;  /* next structure in linked list */
};

各个参数以及含义可以参照《Linux下网络相关结构体 struct addrinfo》。此外,其属性ai_addr即包含了地址信息。sockaddr类型的简介,可以参考《sockaddr和sockaddr_in详解》。

由于一个域名可以对应多个IP地址,addrinfo也就支持了这个场景。addrinfo通过链表的方式存储其他地址的,可以遍历其属性ai_next获得。

相关方法

1. getaddrinfo(const char, const char, const struct addrinfo, struct addrinfo*)

该方法可参考《getaddrinfo详解》。

2. freeaddrinfo(struct addrinfo*)

在上面介绍getaddrinfo时,传入了参数addrinfo用于保存查询的结果。查看该方法的实现,其在内部调用了calloc动态申请了内存,并将结果保存到了传入的参数中,因此在使用getaddrinfo成功获取到地址后,必须要对该部分内存进行释放。freeaddrinfo即是netdb.h提供的释放内存方法。其实现如下

void freeaddrinfo(struct addrinfo *ai)
{struct addrinfo *next;#if defined(__BIONIC__)if (ai == NULL) return;
#else_DIAGASSERT(ai != NULL);
#endifdo {next = ai->ai_next;if (ai->ai_canonname)free(ai->ai_canonname);/* no need to free(ai->ai_addr) */free(ai);ai = next;} while (ai);
}

从其实现可以看出,freeaddrinfo通过循环遍历ai_next进行一层一层的内存释放。此外,通过其实现,可以看到该方法显示的释放了ai_canoname属性以及其本身,这就说明当我们在对addrinfo进行内存拷贝的时候,就要注意对ai_canonname和ai_next的深拷贝的问题。
而上述逻辑中有句注释“no need to free(ai->ai_addr)”,一开始对这个不甚理解,该属性同样是一个指针,为什么不需要对其指向的内容释放呢?经过证明,如果不对该部分进行深拷贝,拷贝的结果是很容易出问题的。但是如果拷贝的时候,直接显式的调用malloc动态申请内存,那么在freeaddrinfo的时候就必须要显式的调用free方法,对该部分指向的内存进行释放,否则必然会造成内存泄漏。为了搞清楚这个问题,必须要深入getaddrinfo方法找到系统对addrinfo赋值的地方。

//bionic/libc/dns/net/getaddrinfo.c
static int android_getaddrinfo_proxy(const char *hostname, const char *servname,const struct addrinfo *hints, struct addrinfo **res, unsigned netid)
{……while (1) {struct addrinfo* ai = calloc(1, sizeof(struct addrinfo) + sizeof(struct sockaddr_storage));if (ai == NULL) {break;}ai->ai_addr = (struct sockaddr*)(ai + 1);……ai->ai_canonname = (char*) malloc(name_len);……*nextres = ai;nextres = &ai->ai_next;}
}

通过上述实现可以发现,原来addrinfo在申请地址的时候直接申请的是addrinfo大小外加一个sockaddr的大小,其属性ai_addr所指向的地址内容是紧跟在addrinfo 结构后面的,因此在对其赋值的时候是直接ai->ai_addr = (struct sockaddr*)(ai + 1);这也就解释了为什么在freeaddrinfo的时候没有显式的调用free(ai_addr),其在free(ai)的时候就同步释放了。

3. 拷贝addrinfo结构

在netdb.h中并没有提供拷贝addrinfo结构的方法,因此这个方法需要自己实现。下面是我的一个实现方案,仅供参考。

int dumpAddrInfo(struct addrinfo **dst, struct addrinfo *src) {if (src == NULL) return -1;int ret = 0;struct addrinfo *aiDst = NULL, *aiSrc = src, *aiCur = NULL;while(aiSrc) {size_t aiSize = sizeof(struct addrinfo) + sizeof(struct sockaddr_storage);struct addrinfo* ai = (struct addrinfo*) calloc(1, aiSize);if (ai == NULL) {ret = -1;break;}memcpy(ai, aiSrc, aiSize);ai->ai_addr = (struct sockaddr*)(ai + 1);ai->ai_next = NULL;if (aiSrc->ai_canonname != NULL) {ai->ai_canonname = strdup(aiSrc->ai_canonname);}if (aiDst == NULL) {aiDst = ai;} else {aiCur->ai_next = ai;}aiCur = ai;aiSrc = aiSrc->ai_next;}if (ret) {freeaddrinfo(aiDst);return ret;}*dst = aiDst;return ret;
}

linux 结构体 struct addrinfo 简介相关推荐

  1. Linux下网络相关结构体 struct addrinfo

    参考书籍:<UNIX环境高级编程> 参考连接: http://www.cnblogs.com/benxintuzi/p/4589819.html 一.简介 结构体定义如下: struct ...

  2. Linux下网络相关结构体 struct servent

    Linux下网络相关结构体 struct servent 参考书籍:<UNIX环境高级编程> 参考链接: http://www.cnblogs.com/benxintuzi/p/45898 ...

  3. linux sock结构体,struct socket结构体详解

    在内核中为什么要有struct socket结构体呢? struct socket结构体的作用是什么? 下面这个图,我觉得可以回答以上两个问题.  由这个图可知,内核中的进程可以通过使用struct ...

  4. 内核中用于数据接收的结构体struct msghdr

    我们从一个实际的数据包发送的例子入手,来看看其发送的具体流程,以及过程中涉及到的相关数据结构.在我们的虚拟机上发送icmp回显请求包,ping另一台主机172.16.48.1.我们使用系统调用send ...

  5. 获取网络接口信息——ioctl()函数与结构体struct ifreq、 struct ifconf

    http://blog.csdn.net/windeal3203/article/details/39320605 Linux 下 可以使用ioctl()函数 以及 结构体 struct ifreq ...

  6. (15)System Verilog结构体struct详解

    (15)System Verilog结构体struct详解 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog结构体struct详解 5) ...

  7. Linux结构体变量报错,C语言中的结构体

    用户自己建立自己的结构体类型 1.  定义和使用结构体变量 (1).结构体的定义 C语言允许用户自己建立由不同类型数据组成的组合型的数据结构,它称为结构体. (2).声明一个结构体类型的一般形式为: ...

  8. 结构体struct的自然对齐问题(经典)

    结构体struct的自然对齐问题下面的机构体 struct A {     char c;     int i;     char cc; }; 它的sizeof()是多少呢? 如果是紧凑对齐的话,当 ...

  9. 谈结构体struct 初始化多出的点号“.”,数组[]初始化多出的逗号“,”

    结构体struct初始化多出的点号"." 在阅读GNU/Linux内核代码时,我们会遇到一种特殊的结构初始化方式,该方式是书中并没有介绍过的. 这种方式称为指定初始化(design ...

最新文章

  1. Python中的变量以及赋值语句
  2. C#.NET学习笔记---C#中的条件编译
  3. STL的deque容器
  4. hdu 1280 前m大的数 哈希
  5. webpack中跨域请求proxy代理(vue与react脚手架不同设置方法)
  6. 如何在ashx页面获取Session值(未将对象引用设置到对象的实例) (转)
  7. 《C Traps and Pitfalls》 笔记
  8. LeetCode —— 365. 水壶问题(Python3)
  9. Keras-9 实现Seq2Seq
  10. [转]自己写PHP扩展之创建一个类
  11. PCB Dk、Df和介质损耗
  12. 另外一台电脑打开html,有的网页你打不开,在别的电脑就能打开,这样处理就解决了...
  13. 关于Unable to read additional data from server sessionid 0x0问题的解决。
  14. 史上最强模型 GPT-4 上线:一张手绘草图能生一个网站、60 秒搞定一个游戏开发!
  15. 脱离鼠标后必须记住地快捷命令方式
  16. 22061周市场回顾
  17. 洗衣店小程序v2.6.5+小程序前端全开源版安装教程
  18. React Navigation 基本使用
  19. 第四方支付平台有哪些?
  20. 百度网盘全速下载破解工具

热门文章

  1. IBM确定公司未来存储技术发展方向
  2. mysql 多表 三表 删除_mysql 多表join查询索引优化
  3. 大整数减法c语言_C语言学习笔记(一)
  4. 2021/11/24 微软亚州研究院游记
  5. 用 Flask 来写个轻博客 (19) — 以 Bcrypt 密文存储账户信息与实现用户登陆表单
  6. OSS 下载延迟或超时
  7. 开发人员应该对IIS理论层的知识了解的多一些~第四讲 HttpModule中的几大事件
  8. 再说TCP神奇的40ms
  9. shell中判断空字符串和有趣的空字符串
  10. 理解同步异步、阻塞与非阻塞