通过域名获取主机IP -- struct addrinfo
发布日期:2021-06-30 19:46:25
浏览次数:2
分类:技术文章
本文共 3533 字,大约阅读时间需要 11 分钟。
参考书籍:《UNIX环境高级编程》 (APUE,男神的书,出第三版了,有需要的私信我)
文章目录
结构体定义
addrinfo结构主要在网络编程解析hostname时使用,其在头文件#include<netdb.h>中,定义如下:
struct addrinfo{ int ai_flags; /* Input flags. */ int ai_family; /* Protocol family for socket. */ int ai_socktype; /* Socket type. */ int ai_protocol; /* Protocol for socket. */ socklen_t ai_addrlen; /* Length of socket address. */ struct sockaddr *ai_addr; /* Socket address for socket. */ char *ai_canonname; /* Canonical name for service location. */ struct addrinfo *ai_next; /* Pointer to next in list. */};
可以说是新面孔,也可以说是老面孔,那我来介绍一下?
那就介绍一下:好的其实它的介绍已经挺明白了。跟sin_addr和s_addr差不多。
参数释义:
ai_flags
用来指定如何处理地址和名字,可取得值如下:
就改个前缀,是吧
ai_family
这里直接连前缀都不改了
ai_socktype
同上
ai_protocol
IPPROTO_IP :IP协议IPPROTO_IPV4 :IPv4IPPROTO_IPV6 :IPv6IPPROTO_TCP :TCPIPPROTO_UDP :UDP
这个改动的东西比较多。
ai_next
由于一个域名可以对应多个IP地址,addrinfo也就支持了这个场景。addrinfo通过链表的方式存储其他地址的,可以遍历其属性ai_next获得。
相关函数
getaddrinfo
找了一圈也找不到它的源码,只能把声明贴出来了,什么时候找着了再补上来。
int getaddrinfo(const char *restrict nodename, /* host 或者IP地址 */ const char *restrict servname, /* 十进制端口号 或者常用服务名称如"ftp"、"http"等 */ const struct addrinfo *restrict hints, /* 获取信息要求设置 */ struct addrinfo **restrict res); /* 获取信息结果 */
参数释义:
nodename:
主机名(“lion-wu.blog.csdn.net”)或者是数字化的地址字符串(IPv4的点分十进制串(“192.168.128.64”)或者IPv6的16进制串)。 如果 ai_flags 中设置了AI_NUMERICHOST 标志,那么该参数只能是数字化的地址字符串,不能是域名,该标志的作用就是阻止进行域名解析。 nodename 和 servname 可以设置为NULL,但是同时只能有一个为NULL。servname:
服务名可以是十进制的端口号(“8080”)字符串,也可以是已定义的服务名称,如"ftp"、"http"等,详细请查看/etc/services 文件,最后翻译成对应服务的端口号。如果此参数设置为NULL,那么返回的socket地址中的端口号不会被设置。 如果 ai_flags 设置了AI_NUMERICSERV 标志并且该参数未设置为NULL,那么该参数必须是一个指向10进制的端口号字符串,不能设定成服务名,该标志就是用来阻止服务名解析。hints:
该参数指向用户设定的 struct addrinfo 结构体,只能设定该结构体中 ai_family、ai_socktype、ai_protocol 和 ai_flags 四个域,其他域必须设置为0 或者 NULL, 通常是申请 结构体变量后使用memset()初始化再设定指定的四个域。 该参数可以设置为NULL,等价于 ai_socktype = 0, ai_protocol = 0,ai_family = AF_UNSPEC,ai_flags = 0。res:
该参数获取一个指向存储结果的 struct addrinfo 结构体列表,使用完成后调用 freeaddrinfo() 释放存储结果空间。返回值
如果 getaddrinfo() 函数执行成功,返回值为 0 , 其他情况返回值表示错误种别。使用函数gai_strerror() 可以获取可读性的错误信息,用法用strerror()相同。
栗子
ret = getaddrinfo("lion-wu.blog.csdn.net", NULL, &hint, &res); if (ret != 0) { printf("getaddrinfo error\n"); return -1; }
freeaddrinfo
void freeaddrinfo(struct addrinfo *ai){ struct addrinfo *next;#if defined(__BIONIC__) if (ai == NULL) return;#else _DIAGASSERT(ai != NULL);#endif do { 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);}
使用示例
#include#include #include #include #include #include int main(int argc, char **argv){ int ret = -1; struct addrinfo *res; struct addrinfo hint; struct addrinfo *curr; char ipstr[16]; if (argc != 2) { printf("parameter error\n"); return -1; } bzero(&hint, sizeof(hint)); hint.ai_family = AF_INET; hint.ai_socktype = SOCK_STREAM; ret = getaddrinfo(argv[1], NULL, &hint, &res); if (ret != 0) { printf("getaddrinfo error\n"); return -1; } for (curr = res; curr != NULL; curr = curr->ai_next) { inet_ntop(AF_INET,&(((struct sockaddr_in *)(curr->ai_addr))->sin_addr), ipstr, 16); printf("%s\n", ipstr); } freeaddrinfo(res); return 0;}
亲测:
能猜到为啥第一次操作失败了吗?
今天的技术介绍就到这里啦,我要介绍一位我的新朋友:
我们学校软件工程系的大佬,Java、算法、redis领域博主,正在厚积薄发当中。然后,顺便也可以看看我的其他博客,lion-wu.blog.csdn.net
刷一下就过去了,确定不留下吗?
转载地址:https://lion-wu.blog.csdn.net/article/details/108521905 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
初次前来,多多关照!
[***.217.46.12]2024年04月10日 15时27分03秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
Python量子计算qiskit
2019-04-30
Python的多线程不是真的多线程(GIL全局解释器锁)
2019-04-30
Python手动读取MNIST数据集
2019-04-30
Python手动读取CIFAR-10数据集
2019-04-30
Pytorch(十一) —— 分布式(多GPU)训练
2019-04-30
Deeplab v3
2019-04-30
tensor/矩阵/图片等更换通道,调整size
2019-04-30
本地和colab 中 改变tensorflow的版本
2019-04-30
Camera-ready ddl
2019-04-30
CUB-200鸟类数据集
2019-04-30
Python反射机制
2019-04-30
YAPF —— Python代码格式化工具
2019-04-30
UGC 用户产生内容
2019-04-30
ranger
2019-04-30
slurm
2019-04-30
xfce4
2019-04-30
xrdp
2019-04-30
Raft算法
2019-04-30
Python计算文本BLEU分数
2019-04-30