使用到的数据结构
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等