在用 C/C++ 编写 socket 程序时,给相关函数传入网络地址时总是会卡一下,有必要总结一下。
具体而言,有以下几个结构体可以表示 IPV4 网络地址:
struct sockaddr
{
unsigned short sa_family; //地址协议簇
char sa_data[14]; //这 14 个字节表示了 IP 地址和端口,目测是 4 个 3 位整数(0 ~ 255),每一位用一个字节存放,占了 4 * 3 * 1 = 12字节,再加上两个字节表//示端口号,端口号的范围是 2 ^ 16 - 1 = 65536 - 1。
}; // 16 字节
第二个结构体是
struct sockaddr_in
{
short int sin_family; //地址协议簇
unsigned short int sin_port;//端口号
struct in_addr sin_addr;//IP 地址
unsigned char sin_zero[8]; //填充字节,保证sockaddr 与 sockaddr_in 的大小一样大。
};
它用到了 struct in_addr 这个结构体,定义如下:
struct in_addr
{
union
{
struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
struct { u_short s_w1,s_w2; } S_un_w;
u_long S_addr; //实际上,在 unix 系统中,in_addr 只有这一个成员
} S_un;
};
注意 in_addr 是一个联合结构,即,它有着不同的 "view",你可以把它看成任何一种它里面声明的类型。画出其内存结构如下:
in_addr 占4个字节
我们细看 sockaddr 和 sockaddr_in 这两个成员,不管它们以 2 字节,4 字节,还是 8 字节的内存对齐方式,都是 16 字节大小。
内存对齐可以参看另一篇文章,《内存对齐》