使用到的数据结构
struct addrinfo { int ai_flags; int ai_family; int ai_socktype; int ai_protocol; size_t ai_addrlen; struct sockaddr *ai_addr; char *ai_canonname; struct addrinfo *ai_next; };
struct sockaddr_in { sa_family_t sin_family; /* Address family */ __be16 sin_port; /* Port number */ struct in_addr sin_addr; /* Internet address */ /* Pad to size of `struct sockaddr'. */ unsigned char __pad[__SOCK_SIZE__ - sizeof(short int) - sizeof(unsigned short int) - sizeof(struct in_addr)]; };
struct in_addr { __be32 s_addr; };
hint是用于过滤地址的模版。只选取ai_flags,ai_type,ai_family,ai_protocol,用来指定如何处理地址和名字。
addrgetinfo()取得输入主机和服务的 addrinfo解构,按照hint的过滤作用保存在ailist中,依次打印flag,type等,在通过定义struct sockaddr_in snip来保存AF_INET family 这一簇地址格式的 aip->ai_addr;使用inet_ntop()函数把得到的地址信息解析出来,放到addr指针域,打印出来。
全文代码如下:
#include <fcntl.h> #include "apue.h" #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> void printf_family(struct addrinfo *aip) { printf("\n"); 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("unkown "); printf("\n"); } } void printf_type(struct addrinfo *aip) { printf("\n"); printf("type:"); switch(aip->ai_socktype) { case SOCK_STREAM: printf("sream"); break; case SOCK_DGRAM: //不固定的。长度不可靠的报文 printf("datagram"); break; case SOCK_SEQPACKET: printf("seqpacket");//长度固顶有序,面向连接的报文 break; case SOCK_RAW: printf("raw");//面向底层ip协议的套接字 break; default: printf("unkown (%d)",aip->ai_socktype); } } void printf_protocol(struct addrinfo *aip) { printf("\n"); 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");//面向底层ip协议的套接字 break; default: printf("unkown (%d)",aip->ai_protocol); printf("\n"); } } void printf_flags(struct addrinfo *aip) { printf("\n"); 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("cannoname"); if(aip->ai_flags&AI_NUMERICHOST) printf("numhost"); #if defined (AI_V4MAPPED) if(aip->ai_flags&AI_V4MAPPED) printf("v4mampped"); #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 *snip; const char *addr; char abuf[INET_ADDRSTRLEN]; int err; if(argc!=3) err_sys("usage: %s nodename service ",argv[0]); hint.ai_flags=AI_CANONNAME; hint.ai_socktype=0; hint.ai_protocol=0; hint.ai_family=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) err_quit("getaddrinfor error:%s",gai_strerror(err)); for(aip=ailist;aip!=NULL;aip=ailist->ai_next) { printf_flags(aip); printf_type(aip); printf_protocol(aip); printf_family(aip); printf("\n\t host %s\n",aip->ai_canonname?aip->ai_canonname:"-"); if((aip->ai_family==AF_INET)) { snip=(struct sockaddr_in *)aip->ai_addr; addr=inet_ntop(AF_INET,&snip->sin_addr,abuf,INET_ADDRSTRLEN); printf("address %s\n",addr?addr:"unkown \n"); printf("port %d\n",ntohs(snip->sin_port)); } } exit(0); }
执行时 使用 ./a.out 192.168.0.1 nfs便可
可以查看的服务 有 nfs,tftp,telnet等