各类资料学习下载合集
链接:https://pan.quark.cn/s/7c8c391011eb
一、 为什么必须 Bind?
在 TCP 通信中,服务器的角色就像是一家实体店。
- Socket:相当于你注册了营业执照。
- Bind:相当于你租下了一个具体的门面(IP + 端口)。
如果你不开店(不 Bind),虽然你也可以去逛街(作为客户端连接别人),但顾客(客户端)永远找不到你在哪里。因此,服务器必须绑定固定的 IP 和端口。
二、 结构体的“变装秀”:sockaddrvssockaddr_in
这是 Socket 编程中最让新手困惑的地方:为什么有两个地址结构体?
1. 历史遗留问题
bind函数设计之初,是为了支持所有协议(IPv4, IPv6, UNIX 域等)。因此,它的参数类型是通用的struct sockaddr*。
2. 内存布局对比
为了方便程序员操作,针对 IPv4 协议,系统提供了专用的struct sockaddr_in。好消息是,它们在内存中的大小完全一样(16字节),可以直接强转。
| 字节偏移 | struct sockaddr(通用) | struct sockaddr_in(IPv4专用) |
|---|---|---|
| 0 - 1 | sa_family(地址族) | sin_family(地址族,如 AF_INET) |
| 2 - 3 | sa_data(混合数据) | sin_port(端口号) |
| 4 - 7 | … | sin_addr(IP地址) |
| 8 - 15 | … | sin_zero(填充字节,为了凑齐16字节) |
最佳实践:我们在代码中定义和填充
sockaddr_in,但在调用bind时,将其强制类型转换为sockaddr*。
三、 Bind 函数详解
intbind(intsockfd,conststructsockaddr*addr,socklen_taddrlen);- 参数 1 (
sockfd):通过socket()创建的文件描述符。 - 参数 2 (
addr):指向地址结构体的指针(需强转)。 - 参数 3 (
addrlen):结构体的大小,通常写sizeof(struct sockaddr_in)。