您的位置:首页 > 编程语言

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

2016-07-15 14:15 417 查看
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; /* length in bytes of address */

struct sockaddr *ai_addr; /* address */

char *ai_canonname; /* canonical name of host */

struct addrinfo *ai_next; /* next in 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: 0 if OK, nonzero error code on error

void freeaddrinfo(struct addrinfo *ai);


[b]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);

}
[/b]

代码说明: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#
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息