linux 结构体 struct addrinfo 简介
目录
定义
相关方法
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 简介相关推荐
- Linux下网络相关结构体 struct addrinfo
参考书籍:<UNIX环境高级编程> 参考连接: http://www.cnblogs.com/benxintuzi/p/4589819.html 一.简介 结构体定义如下: struct ...
- Linux下网络相关结构体 struct servent
Linux下网络相关结构体 struct servent 参考书籍:<UNIX环境高级编程> 参考链接: http://www.cnblogs.com/benxintuzi/p/45898 ...
- linux sock结构体,struct socket结构体详解
在内核中为什么要有struct socket结构体呢? struct socket结构体的作用是什么? 下面这个图,我觉得可以回答以上两个问题. 由这个图可知,内核中的进程可以通过使用struct ...
- 内核中用于数据接收的结构体struct msghdr
我们从一个实际的数据包发送的例子入手,来看看其发送的具体流程,以及过程中涉及到的相关数据结构.在我们的虚拟机上发送icmp回显请求包,ping另一台主机172.16.48.1.我们使用系统调用send ...
- 获取网络接口信息——ioctl()函数与结构体struct ifreq、 struct ifconf
http://blog.csdn.net/windeal3203/article/details/39320605 Linux 下 可以使用ioctl()函数 以及 结构体 struct ifreq ...
- (15)System Verilog结构体struct详解
(15)System Verilog结构体struct详解 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog结构体struct详解 5) ...
- Linux结构体变量报错,C语言中的结构体
用户自己建立自己的结构体类型 1. 定义和使用结构体变量 (1).结构体的定义 C语言允许用户自己建立由不同类型数据组成的组合型的数据结构,它称为结构体. (2).声明一个结构体类型的一般形式为: ...
- 结构体struct的自然对齐问题(经典)
结构体struct的自然对齐问题下面的机构体 struct A { char c; int i; char cc; }; 它的sizeof()是多少呢? 如果是紧凑对齐的话,当 ...
- 谈结构体struct 初始化多出的点号“.”,数组[]初始化多出的逗号“,”
结构体struct初始化多出的点号"." 在阅读GNU/Linux内核代码时,我们会遇到一种特殊的结构初始化方式,该方式是书中并没有介绍过的. 这种方式称为指定初始化(design ...
最新文章
- Python中的变量以及赋值语句
- C#.NET学习笔记---C#中的条件编译
- STL的deque容器
- hdu 1280 前m大的数 哈希
- webpack中跨域请求proxy代理(vue与react脚手架不同设置方法)
- 如何在ashx页面获取Session值(未将对象引用设置到对象的实例) (转)
- 《C Traps and Pitfalls》 笔记
- LeetCode —— 365. 水壶问题(Python3)
- Keras-9 实现Seq2Seq
- [转]自己写PHP扩展之创建一个类
- PCB Dk、Df和介质损耗
- 另外一台电脑打开html,有的网页你打不开,在别的电脑就能打开,这样处理就解决了...
- 关于Unable to read additional data from server sessionid 0x0问题的解决。
- 史上最强模型 GPT-4 上线:一张手绘草图能生一个网站、60 秒搞定一个游戏开发!
- 脱离鼠标后必须记住地快捷命令方式
- 22061周市场回顾
- 洗衣店小程序v2.6.5+小程序前端全开源版安装教程
- React Navigation 基本使用
- 第四方支付平台有哪些?
- 百度网盘全速下载破解工具