1 addrinfo
addrinfo
结构内容如下:
struct addrinfo {
int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */
int ai_family; /* PF_xxx */
int ai_socktype; /* SOCK_xxx */
int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */
socklen_t ai_addrlen; /* length of ai_addr */
char *ai_canonname; /* canonical name for hostname */
struct sockaddr *ai_addr; /* binary address */
struct addrinfo *ai_next; /* next structure in linked list */
};
1.1 ai_family
ai_family
指定了地址族,可取值如下:
值 | 取值 | 含义 |
---|---|---|
AF_INET | 2 | IPv4 |
AF_INET6 | 23 | IPv6 |
AF_UNSPEC | 0 | 协议无关 |
void print_family(struct addrinfo *aip)
{
printf(" family ");
switch (aip->ai_family) {
case AF_INET:
printf("inet");
break;T
case AF_INET6:
printf("inet6");
break;
case AF_UNIX:
printf("unix");
break;
case AF_UNSPEC:
printf("unspecified");
break;
default:
printf("unknown");
}
}
1.2 ai_socketype
值 | 取值 | 含义 |
---|---|---|
SOCK_STREAM | 1 | 数据流协议 |
SOCK_DGRAM | 2 | 数据报协议 |
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);
}
}
1.3 ai_protocol
值 | 取值 | 含义 |
---|---|---|
IPPROTO_IP | 0 | IP协议 |
IPPROTO_IPV4 | 4 | IPv4 |
IPPROTO_IPV6 | 41 | IPv6 |
IPPROTO_UDP | 17 | UDP |
IPPROTO_TCP | 6 | TCP |
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);
}
}
1.4 ai_flags
值 | 取值 | 含义 |
---|---|---|
AI_PASSIVE | 1 | 被动的,用于bind,通常用于server socket |
AI_CANONNAME | 2 | 用于返回主机的规范名称 |
AI_NUMERICHOST | 4 | 地址为数字串 |
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
}
}
1.5 sockaddr
套接字*二级制表示。详见第2节。
2. sockaddr
& sockaddr_in
sockaddr
:
struct sockaddr {
unsigned short sa_family; /* address family, AF_xxx */
char sa_data[14]; /* 14 bytes of protocol address */
};
- sa_family是地址家族,一般都是“AF_xxx”的形式。好像通常大多用的是都是AF_INET
- sa_data是14字节协议地址
此数据结构用做bind、connect、recvfrom、sendto等函数的参数,指明地址信息。但一般编程中并不直接针对此数据结构操作,而是使用另一个与sockaddr等价的数据结构:sockaddr_in
:
// sockaddr_in(在netinet/in.h中定义):
struct sockaddr_in {
short int sin_family; /* Address family */
unsigned short int sin_port; /* Port number */
struct in_addr sin_addr; /* Internet address */
unsigned char sin_zero[8]; /* Same size as struct sockaddr */
};
struct in_addr {
__be32 s_addr;
};
- sin_family指代协议族,在socket编程中只能是AF_INET
- sin_port存储端口号(使用网络字节顺序)
- sin_addr存储IP地址,使用in_addr这个数据结构,sin_addr按照网络字节顺序存储IP地址
- sin_zero是为了让
sockaddr
与sockaddr_in
两个数据结构保持大小相同而保留的空字节。
sockaddr_in
和sockaddr
是并列的结构,指向sockaddr_in
的结构体的指针也可以指向sockadd
的结构体,并代替它。也就是说,你可以使用sockaddr_in
建立你所需要的信息,
在最后用进行类型转换就可以了bzero((char*)&mysock,sizeof(mysock));
//初始化:
mysock; // 结构体名
mysock.sa_family=AF_INET;
mysock.sin_addr.s_addr=inet_addr("192.168.0.1");