使用getaddrinfo 打印主机和服务信息

使用到的数据结构

           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等

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值