1. 程式人生 > >APUE第16章的示例執行16-8

APUE第16章的示例執行16-8

最近在學習APUE第十六章的時候老是在執行的關口卡住,現將自己或別人的解決辦法拿出來共享,有更好辦法的希望拿出來和大家晒晒………

APUE的16-8.c是將命令列給出的主機名和服務中的資訊通過getaddrinfo對映到IP地址和埠,並打印出一些主機名、協議型別、埠資訊等

程式碼:

#include "apue.h" //注意,這個標頭檔案是APUE前面講到的一些常用的函式,在此沒有給出,所以不能直接執行!
#include <netdb.h>
#include <arpa/inet.h>
#if defined(BSD) || defined(MACOS)
#include <sys/socket.h>
#include <netinet/in.h>
#endif

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");
	}
	return;
}

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("ram"); break;
	default: printf("unknown(%d)\n", aip->ai_socktype);
	}
	return;
}

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("unknow(%d)", aip->ai_protocol);
	}
	return;
}

void print_flags(struct addrinfo *aip)
{
	printf(" flag: ");
	if (aip->ai_flags == 0) {
		printf(" 0");
	} else {
		if (aip->ai_flags & AI_PASSIVE)
			printf(" passive ");
		if (aip->ai_flags & AI_CANONNAME)
			printf(" canonname ");
		if (aip->ai_flags & AI_NUMERICHOST)
			printf(" numerichost ");
#if defined(AI_NUMERICSERV)
		if (aip->ai_flags & AI_NUMERICSERV)
			printf(" numricserv ");
#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
	}
	return;
}
//if you want test this program, please type "./a.out IP_addr service_name", for example, ./a.out 192.168.1.1 nfs
int main(int argc, char *argv[])
{
	struct addrinfo 	*aip, *ailist;
	struct addrinfo 	hint;
	struct sockaddr_in 	*sinp;
	const char 			*addr;
	int					err;
	char 				abuf[INET_ADDRSTRLEN];
	
	if (argc != 3) 
		err_quit("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) //你傳入的引數都派上了用場
		err_quit("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);
}

APUE上給出的執行方式為:./a.out harry nfs

在執行時如果完全按照APUE上的可能得不到結果,因為你要確保你的linux/Unix上有harry這個使用者/主機,,其實就是給出相應的地址,所以我在執行時搗鼓了半天準備放棄,最後靈光了一下,用如下辦法得出結果:./a.out 127.0.0.1 nfs 

注:127.0.0.1是迴環測試地址

另外,你可以通過檢視/etc/hosts中的內容,會看到有IP和名字對應的資訊(我的前兩行分別是localhost和Uuntu及其對應的IP),你可以用裡面有的IP或名字來使用,包括APUE的16章後面的內容都能用到,去看一下吧!