getaddrinfo函数返回No such file or directory的分析

在项目中实现NTP功能模块时,为了更好的兼容和更小的警告,将gethostbyname函数用getaddrinfo函数进行了替代,可是在开发板上运行时却遇到了这个错误:

getaddrinfo fail for host time.windows.com:System error
error:No such file or directory
然而同样的代码程序在PC上运行是正确的。可以确定是开发板上的文件系统环境缺少某个与网络相关的配置文件导致getaddrinfo系统调用执行失败,问题在于是哪一个文件,怎么来找到它?答案是使用strace工具在追踪getaddrinfo在PC上执行是的文件访问记录,从而找出缺少的配置文件。

为了减少干扰,使用一个简单的test程序来进行分析,使用如下命令得到追踪记录:

# strace -e trace=file -o 2.strace ./test_getaddrinfo
追踪记录文件信息如下(为了保持strace文件的语法高亮,这里使用图片):

滤掉程序执行涉及的动态库链接缓存之类的文件(因为程序运行起来了),就只剩下三个文件了:/etc/host.conf  /etc/hosts  /etc/resolv.conf.

/etc/resolv.conf文件是域名解析服务器列表的参数文件,实现域名解析,必须设置域名服务器的地址,开发板上已经配置了。

/etc/hosts 文件是主机地址列表参数文件,指定本机的ip地址和主机名称,是域名解析的优先参考映射,即先查看该文件,然后才查询DNS,开发板上不存在该文件。

于是添加该文件到开发板上,通过以下命令:

# echo "127.0.0.1 localhost" > /etc/hosts
然后再次运行程序,getaddrinfo解析域名成功,不再返回System Error的错误。

为了保证getaddrinfo之类接口的正确运行,可以采用两者途径来确保配置环境的OK:

1. 在制作设备的根文件系统时,保证上述配置文件的存在及正确。

2. 在应用程序中检测,如果不存在就创建配置文件。我在NTP的实现中就采用了这一个方法:

if(access("/etc/hosts",F_OK))
    {// create the file for getaddrinfo api
        system("echo \"127.0.0.1   localhost\" > /etc/hosts");
    }

转载于:https://my.oschina.net/shelllife/blog/297156

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
getaddrinfo函数是用于将主机名和服务名转化为套接字地址的函数。该函数可以根据传入的参数获取与主机名和服务名相匹配的地址信息,返回一个addrinfo结构体链表,每个结构体包含了主机名、服务名、协议、IP地址等信息。 下面是该函数的使用方法: ```c #include <sys/types.h> #include <sys/socket.h> #include <netdb.h> int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res); ``` 其中,node表示主机名或IP地址,service表示服务名或端口号,hints表示筛选条件,res表示返回addrinfo结构体链表。 示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <netdb.h> #include <arpa/inet.h> int main(int argc, char *argv[]) { struct addrinfo hints, *res; int status; memset(&hints, 0, sizeof hints); // 清空hints结构体 hints.ai_family = AF_UNSPEC; // 既可以是IPv4也可以是IPv6 hints.ai_socktype = SOCK_STREAM; // 流式套接字 if (argc != 2) { fprintf(stderr, "usage: %s hostname\n", argv[0]); return 1; } if ((status = getaddrinfo(argv[1], NULL, &hints, &res)) != 0) { fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status)); return 2; } printf("IP addresses for %s:\n\n", argv[1]); struct addrinfo *p; char ipstr[INET6_ADDRSTRLEN]; for (p = res; p != NULL; p = p->ai_next) { void *addr; char *ipver; if (p->ai_family == AF_INET) { // IPv4 struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr; addr = &(ipv4->sin_addr); ipver = "IPv4"; } else { // IPv6 struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr; addr = &(ipv6->sin6_addr); ipver = "IPv6"; } inet_ntop(p->ai_family, addr, ipstr, sizeof ipstr); printf("%s: %s\n", ipver, ipstr); } freeaddrinfo(res); // 释放addrinfo链表 return 0; } ``` 该程序接受一个主机名作为命令行参数,然后使用getaddrinfo函数获取该主机名对应的IP地址信息,并打印出所有的IP地址。其中,将hints结构体的ai_family成员设置为AF_UNSPEC表示既可以是IPv4也可以是IPv6,hints结构体的ai_socktype成员设置为SOCK_STREAM表示流式套接字。在for循环中,判断addrinfo结构体的ai_family成员,来确定IPv4或IPv6的地址信息,并使用inet_ntop函数将网络字节序转换为主机字节序的IP地址,并打印出来。最后,记得释放addrinfo链表。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值