IPv4套接字地址结构学习
最近准备从头学习下*nix下的网络编程,参考资料为 unix网络编程 和 The Linux Programming Interface.
IPv4套接字地址结构以sockaddr_in命名,定义在<netinet/in.h>头文件中.
我的系统环境为Arch x86_64 GNU/LINUX,该结构体的定义如下
/* Structure describing an Internet socket address. */ struct sockaddr_in { __SOCKADDR_COMMON (sin_); in_port_t sin_port; /* Port number. */ struct in_addr sin_addr; /* Internet address. */ /* Pad to size of `struct sockaddr'. */ unsigned char sin_zero[sizeof (struct sockaddr) - __SOCKADDR_COMMON_SIZE - sizeof (in_port_t) - sizeof (struct in_addr)]; };
其中 __SOCKADDR_COMMON 是一个定义在 <bits/sockaddr.h>中的宏
/* POSIX.1g specifies this type name for the `sa_family' member. */ typedef unsigned short int sa_family_t; /* This macro is used to declare the initial common members of the data types used for socket addresses, `struct sockaddr', `struct sockaddr_in', `struct sockaddr_un', etc. */ #define __SOCKADDR_COMMON(sa_prefix) \ sa_family_t sa_prefix##family
所以结构体中的第一行相当于 sa_family sin_family;
前三行定义了POSIX规范中规定的:sin_family sin_addr和sin_port 三个字段.
32位的IPv4地址有两种访问方法, 假如定义了一个socket s,s.sin_addr将按in_addr结构引用其中的32位IPv4地址,而s.sin_addr.s_addr将按in_addr_t(通常是一个无符号的32位整形)引用.
/* Internet address. */ typedef uint32_t in_addr_t; struct in_addr { in_addr_t s_addr; };
根据 unix网络编程 中描述,这是一个历史遗留问题,早期版本中把in_addr结构定义为多种结构的联合,允许访问一个32位IPv4地址中的所以4个字节,或访问它的两个16位值.在划分A B C类的时期,方便访问其地址中适当的字节.如今已不再需要.