两个结构体如下所示
struct sockaddr {
ushort sa_family;
char sa_data[14];
};
struct sockaddr_in {
short sin_family; //地址族 Socket只能用AF_INET
u_short sin_port; //端口
struct in_addr sin_addr; //IPv4网络地址
char sin_zero[8]; //
};
sockaddr 保留了未定义的区域,sockaddr_in 则定义了具体的成员
一般用sockaddr_in进行地址的装入
大部分用到地址结构的函数则用sockaddr结构体,这是为了扩展性。
这样,函数就不用跟具体的地址结构耦合了.
不过毕竟是C,将sockaddr_in传给接收sockaddr的函数时,
就要做强制类型转换,这种转换成功的前提是,
结构体必须保持上一层结构体已定义成员的顺序,
sockaddr第一个成员是sa_family,所以sockaddr_in的第一个成员也一定是sa_family
还有,更进一步,定义新的sockaddr时,增加成员的总空间还可以超过char[14],
就是可以无限扩展的意思.
函数一样可以正常工作,这就是为什么一般函数当需要一个sockaddr地址结构时,还要求传入一个sockaddr的大小
示例:
struct sockaddr_in saServer;
bind( ListenSocket,(SOCKADDR*) &saServer, sizeof(saServer) );
将一个saServer传入时,强制转换成SOCKADDR* , 接着还要传入saServer的大小
即sockaddr_in的大小,而不是sockaddr的大小
sa_family定义了地址族,不同的地址族地址结构是不同的
所以sa_family成为一种地址类型标识
sockaddr_in地址的domain是AF_INET
可以猜想,所有接收sockaddr结构体的函数,
都先通过sa_family判断地址族从而确定地址结构体的实际类型
这就是C语言中的多态!