一、初识Socket套接字结构体
1、通用套接字结构体类型
struct sockaddr
{
sa_family_t sa_family; //协议簇
char sa_data[14]; //协议簇数据
}
通用套接字结构体可以在不同的协议簇之间进行强制转化,Socket网络编程中几乎所有套接字API函数的形参都是通用套接字结构体struct sockaddr。
存在问题:
- 通用套接字结构体对编程的角度来说,设置很不方便,我们以以太网协议来说,当要设置端口号、IP地址等,那么我需要将端口号与IP地址进行数据组合绑定,然后赋值给该结构,是不能独立赋值。
- 为解决上述问题,以太网协议中经常用到的是下述结构体,这样就可以给人以直观的方式去填充套接字结构体。
2、以太网套接字结构体
struct sockaddr_in
{
u8 sin_len;
u8 sin_family;
u16 sin_port;
struct in_addr sin_addr;
char sin_zero[8];
}
- 结构体成员列表
结构体成员 | 参数含义 | 备注 |
---|---|---|
u8 sin_len | 结构体sockaddr_in的长度 | 一般大小为固定16字节 |
u8 sin_family | 协议族类型 | 见下表 |
u16 sin_port | 16位端口号 | XXX |
struct in_addr sin_addr | 32位IP地址 | INADDR_ANY //表示可以与任何主机通信 |
char sin_zero[8] | //未使用 | 填充位,一般都设置为0 |
- 协议簇列表
协议簇类型(sin_family ) |
参数含义 |
---|---|
AF_INET | 以太网/IPv4协议 |
AF_INET6 | 以太网/IPv6协议 |
AF_LOCAL | Unix域协议/只在本机内通信的套接字 |
AF_ROUTE | 路由套接口 |
AF_KEY | 密钥套接口 |
***Note : *** 我们主要使用的是以太网,所以
sin_family
成员一般都为AF_INET
,有时候我们看到协议簇类型是PF_*
而不是AF*
,这是因为glibc的实现机制是posix,其实都是同一个东西。
存在问题:
- Socket网络编程中几乎所有套接字API函数的形参都是通用套接字结构体
struct sockaddr
,而我们初始化传递的参数是以太网套接字结构体struct sockaddr
类型,这样是否就存在类型不一致的问题?
Exzampp:
// API函数: fun(struct sockaddr)
// 用户实际调用:
int main()
{
struct sockaddr_in;
fun(sockaddr_in); //是否存在问题?
}
问题解答:
- 上述操作完全可以,因为这两个结构体在内存上的大小完全一致都是16个字节,所以隐式的转换不存在其它问题。
- struct sockaddr = struct sockaddr_in 。 (不存在问题)
*图示:两种结构类型的内存存储*