IPv4套接字地址结构学习
原文链接 http://woodrat.xyz/2015/05/18/ipv4%e5%a5%97%e6%8e%a5%e5%ad%97%e5%9c%b0%e5%9d%80%e7%bb%93%e6%9e%84%e5%ad%a6%e4%b9%a0/
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。
最近准备从头学习下*nix下的网络编程,参考资料为 unix网络编程 和 The Linux Programming Interface.
IPv4套接字地址结构以sockaddr_in命名,定义在头文件中.
我的系统环境为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 是一个定义在 中的宏
/* 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类的时期,方便访问其地址中适当的字节.如今已不再需要.