Skip to content

netinet/in.h

地址结构体

  • IPv4地址用结构体sockaddr_in表示,该结构体中包含16位的端口号和32位的IP地址;
  • IPv6地址用结构体sockaddr_in6表示,该结构体中包含16位的端口号、128位的IP地址和一些控制字段;
  • Unix Domain Socket的地址格式定义在sys/un.h中,用结构体sock_addr_un表示。
cpp
struct sockaddr {
    __uint8_t       sa_len;         /* total length */
    sa_family_t     sa_family;      /* [XSI] address family */
    char            sa_data[14];    /* [XSI] addr value */
};

struct sockaddr_in {
    __uint8_t       sin_len;
    sa_family_t     sin_family;
    in_port_t       sin_port;
    struct  in_addr sin_addr;
    char            sin_zero[8];
};

struct in_addr {
    in_addr_t s_addr;
};

各种socket地址结构体的开头都是相同的,前16位表示整个结构体的长度(并不是所有UNIX的实现都有长度字段,如Linux就没有),后16位表示地址类型。

IPv4、IPv6和Unix Domain Socket的地址类型分别定义为常数AF_INET、AF_INET6、AF_UNIX。

这样,只要取得某种sockaddr结构体的首地址,不需要知道具体是哪种类型的sockaddr结构体,就可以根据地址类型字段确定结构体中的内容。

也因此,socket API可以接受各种类型的sockaddr结构体指针做参数,例如bind()、accept()、connect()等函数,这些函数的参数应该设计成void *类型以便接收各种类型的指针,但是sock API的实现早于ANSI C标准化,那时还没有void *类型,因此这些函数的参数都用struct sockaddr *类型表示,在传递参数之前要强制类型转换一下,例如:

cpp
struct sockaddr_in servaddr;
bind(listen_fd, (struct sockaddr *)&servaddr, sizeof(servaddr));