侧边栏壁纸
博主头像
noerror

虚灵不寐,众理具而万事出。

  • 累计撰写 238 篇文章
  • 累计创建 9 个标签
  • 累计收到 2 条评论
标签搜索

目 录CONTENT

文章目录

getnameinfo函数用法详解

noerror
2022-11-09 / 0 评论 / 0 点赞 / 32 阅读 / 1,402 字 / 正在检测是否收录...

getnameinfo函数用法详解

getnameinfo函数简介

  • 头文件包含
#include <sys/socket.h>
#include <netdb.h>
  • 函数定义
int getnameinfo(const struct sockaddr * addr , socklen_t  addrlen ,
                char * host , socklen_t  hostlen ,
                char * serv , socklen_t  servlen , int  flags );

getnameinfo函数常见使用错误

  • 编译错误
    warning: implicit declaration of function ‘getnameinfo’ [-Wimplicit-function-declaration]
    解决办法:包含头文件
#include <sys/socket.h>
#include <netdb.h>

getnameinfo函数详细描述

getnameinfo ()函数与getaddrinfo (3):相反,它以独立于协议的方式将套接字地址转换为相应的主机和服务。它结合了gethostbyaddr (3)和getservbyport (3)的功能,但与这些功能不同,getnameinfo ()是可重入的,并允许程序消除IPv4对IPv6的依赖。
addr参数是指向通用套接字地址结构(类型为sockaddr_in或sockaddr_in6 ),大小为addrlen,保存输入IP地址和端口号)的指针。参数host和serv是指向调用方分配的缓冲区(大小分别为hostlen和servlen)的指针,getnameinfo ()将分别包含主机名和服务名的空终止字符串放入该缓冲区。
调用方可以通过提供空host(或serv )参数)或零hostlen(或servlen )参数)来指定不需要主机名(或服务名)。但是,必须至少请求主机名或服务名中的一个。
flags参数修改getnameinfo ()的行为,如下所示:

  • NI_NAMEREQD 如果设置,则如果无法确定主机名,将返回错误。
  • NI_DGRAM 如果设置,则服务是基于数据报(UDP)的,而不是基于流(TCP)的。这对于具有不同UDP和TCP服务的少数端口(512\(en514)是必需的。
  • NI_NOFQDN 如果设置,则仅返回本地主机的完全限定域名的主机名部分。
  • NI_NUMERICHOST 如果设置,则返回主机名的数字形式。(未设置时,在无法确定节点名称的情况下仍会发生这种情况。)
  • NI_NUMERICSERV 如果设置,则返回服务地址的数字形式。(未设置时,在无法确定服务名称的情况下仍会发生这种情况。)Extensions to getnameinfo() for Internationalized Domain Names从glibc 2.3.4开始,getnameinfo ()已经扩展到有选择地允许主机名透明地转换为国际化域名(IDN)格式(参见RFC 3490,"Internationalizing Domain Names in Applications (IDNA)" )定义了三个新标志:
  • NI_IDN 如果使用此标志,则在查找过程中找到的名称将在必要时从IDN格式转换为区域设置的编码。只有ASCII的名称不受转换的影响,这使得该标志可以在现有的程序和环境中使用。
  • NI_IDN_ALLOW_UNASSIGNED " " NI_IDN_USE_STD3_ASCII_RULES设置这些标志将分别启用IDNA_ALLOW_UNASIGNED(允许未分配的Unicode码位)和IDNA_USE_STD3_ASCII_RULES(检查输出以确保它是符合STD3的主机名)标志,以便在IDNA处理中使用。

getnameinfo函数返回值

如果成功,则返回0,并且如果请求,节点和服务名称将填充以空结尾的字符串,这些字符串可能会被截断以适应指定的缓冲区长度。出错时,将返回以下非零错误代码之一:

  • EAI_AGAIN 此时无法解析名称。请稍后再试。
  • EAI_BADFLAGS flags参数的值无效。
  • EAI_FAIL 出现不可恢复的错误。
  • EAI_FAMILY 无法识别地址族,或者指定族的地址长度无效。
  • EAI_MEMORY 内存不足。
  • EAI_NONAME 无法解析提供的参数的名称。已设置 NI_NAMEREQD ,但找不到主机名,或者既没有请求主机名也没有请求服务名。
  • EAI_OVERFLOW host或serv指向的缓冲区太小。
  • EAI_SYSTEM 出现系统错误。错误代码可以在errno 中找到

gai_strerror (3)函数将这些错误代码转换为人类可读的字符串,适用于错误报告。

getnameinfo函数其他说明

为了帮助程序员为所提供的缓冲区选择合理的大小,定义了常量

#define NI_MAXHOST      1025
#define NI_MAXSERV      32

从glibc 2.8开始,这些定义只有在定义了合适的特性测试宏时才会公开,即:_GNU_SOURCE _DEFAULT_SOURCE(从glibc 2.19开始),或者(在glibc 2.19之前的版本中)_BSD_SOURCE或_SVID_SOURCE
前者是BIND的<arpa/nameserh>头文件的最新版本中的常量 MAXDNAME 。后者是基于当前分配号码RFC中列出的服务的猜测。
在glibc 2.2版之前,hostlen和servlen参数被键入为size_t

getnameinfo函数使用举例

下面的代码尝试获取给定套接字地址的数字主机名和服务名。请注意,没有对特定地址族的硬编码引用。

struct sockaddr *addr;     /* input */
socklen_t addrlen;         /* input */
char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];

if (getnameinfo(addr, addrlen, hbuf, sizeof(hbuf), sbuf,
           sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV) == 0)
   printf("host=%s, serv=%s\en", hbuf, sbuf);

以下版本检查套接字地址是否有反向地址映射。

struct sockaddr *addr;     /* input */
socklen_t addrlen;         /* input */
char hbuf[NI_MAXHOST];

if (getnameinfo(addr, addrlen, hbuf, sizeof(hbuf),
           NULL, 0, NI_NAMEREQD))
   printf("could not resolve hostname");
else
   printf("host=%s\en", hbuf);

使用getnameinfo ()的示例程序可以在getaddrinfo (3)中找到

0

评论区