IPv4套接字地址结构学习

2015-05-18 Mithrilwoodrat 更多博文 » 博客 » GitHub »

原文链接 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类的时期,方便访问其地址中适当的字节.如今已不再需要.