socket编程之addrinfo结构体与getaddrinfo函数

addrinfo结构体的定义如下:

  • struct addrinfo {
  •      int ai_flags;/* customize behavior*/
  •      int ai_family;/* address family*/
  •      int ai_socktype;/* socket type*/
  •      int ai_protocol;/* protocol*/
  •      socklen_t ai_addrlen;/* lengthin bytes of address*/
  •      struct sockaddr *ai_addr;/* address*/
  •      char *ai_canonname;/* canonical name of host*/
  •      struct addrinfo *ai_next;/*nextin list*/
  •      .
  •      .
  •      .
  •    };
  • ai_family指定了地址族,可取值如下: 
  • AF_INET          2            IPv4 
  • AF_INET6        23            IPv6 
  • AF_UNSPEC        0            协议无关

ai_socktype指定我套接字的类型 

SOCK_STREAM        1            流 

SOCK_DGRAM        2            数据报

在AF_INET通信域中套接字类型SOCK_STREAM的默认协议是TCP(传输控制协议)

在AF_INET通信域中套接字类型SOCK_DGRAM的默认协议是UDP(用户数据报协议)

ai_protocol指定协议类型。可取的值取决于ai_address和ai_socktype的值

ai_flags指定了如何来处理地址和名字,可取值如下:


getaddrinfo函数 定义及需要的头文件如下:

  • #include <sys/socket.h>
  • #include <netdb.h>
  • int getaddrinfo(const char*restrict host,
  •                 const char*restrict service,
  •                 const struct addrinfo*restrict hint,
  •                 struct addrinfo **restrict res);
  • Returns: 0if OK, nonzeroerror codeonerror
  • void freeaddrinfo(struct addrinfo*ai);

getaddrinfo函数允许将一个主机名字和服务名字映射到一个地址。

使用示例如下:

  • #include<stdio.h>
  • #include<stdlib.h>
  • #include <netdb.h>
  • #include <arpa/inet.h>
  • void
  • print_family(struct addrinfo*aip)
  • {
  •     printf(" family ");
  •     switch (aip->ai_family){
  •     case AF_INET:
  •         printf("inet");
  •         break;
  •     case AF_INET6:
  •         printf("inet6");
  •         break;
  •     case AF_UNIX:
  •         printf("unix");
  •         break;
  •     case AF_UNSPEC:
  •         printf("unspecified");
  •         break;
  •     default:
  •         printf("unknown");
  •     }
  • }
  • void
  • print_type(struct addrinfo*aip)
  • {
  •     printf(" type ");
  •     switch (aip->ai_socktype){
  •     case SOCK_STREAM:
  •         printf("stream");
  •         break;
  •     case SOCK_DGRAM:
  •         printf("datagram");
  •         break;
  •     case SOCK_SEQPACKET:
  •         printf("seqpacket");
  •         break;
  •     case SOCK_RAW:
  •         printf("raw");
  •         break;
  •     default:
  •         printf("unknown (%d)", aip->ai_socktype);
  •     }
  • }
  • void
  • print_protocol(struct addrinfo*aip)
  • {
  •     printf(" protocol ");
  •     switch (aip->ai_protocol){
  •     case 0:
  •         printf("default");
  •         break;
  •     case IPPROTO_TCP:
  •         printf("TCP");
  •         break;
  •     case IPPROTO_UDP:
  •         printf("UDP");
  •         break;
  •     case IPPROTO_RAW:
  •         printf("raw");
  •         break;
  •     default:
  •         printf("unknown (%d)", aip->ai_protocol);
  •     }
  • }
  • void
  • print_flags(struct addrinfo*aip)
  • {
  •     printf("flags");
  •     if(aip->ai_flags== 0){
  •         printf(" 0");
  •     }else{
  •         if(aip->ai_flags& AI_PASSIVE)
  •             printf(" passive");
  •         if(aip->ai_flags& AI_CANONNAME)
  •             printf(" canon");
  •         if(aip->ai_flags& AI_NUMERICHOST)
  •             printf(" numhost");
  • #if defined(AI_NUMERICSERV)
  •         if(aip->ai_flags& AI_NUMERICSERV)
  •             printf(" numserv");
  • #endif
  • #if defined(AI_V4MAPPED)
  •         if(aip->ai_flags& AI_V4MAPPED)
  •             printf(" v4mapped");
  • #endif
  • #if defined(AI_ALL)
  •         if(aip->ai_flags& AI_ALL)
  •             printf(" all");
  • #endif
  •     }
  • }
  • int
  • main(int argc, char*argv[])
  • {
  •     struct addrinfo        *ailist,*aip;
  •     struct addrinfo        hint;
  •     struct sockaddr_in    *sinp;
  •     const char             *addr;
  •     int                 err;
  •     char                 abuf[INET_ADDRSTRLEN];
  •     if(argc!= 3)
  •         printf("usage: %s nodename service", argv[0]);
  •     hint.ai_flags= AI_CANONNAME;
  •     hint.ai_family= 0;
  •     hint.ai_socktype= 0;
  •     hint.ai_protocol= 0;
  •     hint.ai_addrlen= 0;
  •     hint.ai_canonname=NULL;
  •     hint.ai_addr=NULL;
  •     hint.ai_next=NULL;
  •     if((err= getaddrinfo(argv[1], argv[2],&hint,&ailist))!= 0)
  •         printf("getaddrinfo error: %s", gai_strerror(err));
  •     for(aip= ailist; aip!=NULL; aip= aip->ai_next){
  •         print_flags(aip);
  •         print_family(aip);
  •         print_type(aip);
  •         print_protocol(aip);
  •         printf("\n\thost %s", aip->ai_canonname?aip->ai_canonname:"-");
  •         if(aip->ai_family== AF_INET){
  •             sinp =(struct sockaddr_in*)aip->ai_addr;
  •             addr = inet_ntop(AF_INET,&sinp->sin_addr, abuf,INET_ADDRSTRLEN);
  •             printf(" address %s", addr?addr:"unknown");
  •             printf(" port %d", ntohs(sinp->sin_port));
  •         }
  •         printf("\n");
  •     }
  •     exit(0);
  • }

代码说明:sinp = (struct sockaddr_in *)aip->ai_addr;会将struct sockaddr 变量强制转化为struct sockaddr_in 类型

inet_ntop函数用于在二进制格式与点分十进制格式表示(a.b.c.d)之间进行转换

执行结果:#./a X86-PC nfs

  • root@X86-PC:/home/cheney/work-link/linux_C_Test/linux-program/fig16# ./a X86-PC nfs
  • flags canon family inet type stream protocol TCP
  • host X86-PC address 127.0.1.1 port 2049
  • flags canon family inet type datagram protocol UDP
  • host - address 127.0.1.1 port 2049
  • root@X86-PC:/home/cheney/work-link/linux_C_Test/linux-program/fig16#
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值