addrinfo&sockaddr结构解析

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是为了让sockaddrsockaddr_in两个数据结构保持大小相同而保留的空字节。

sockaddr_insockaddr是并列的结构,指向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");
上一篇:云数据库Redis实例如何创建?


下一篇:阿里云双十一活动新鲜出炉!第一重·亿元双十一补贴提前领!!!