套接字和地址
套接字
socket 是我们用来建立连接,传输数据的唯一途径。
套接字接口是一组函数,他们和UNIX I/O函数结合起来,用以创建网络应用。
一旦连接建立,数据的传输就不再是单向的,而是双向的,这也是 TCP 的一个显著特性。
当客户端完成和服务器端的交互后,需要和服务器端断开连接时,就会执行 close 函数,操作系统内核此时会通过原先的连接链路向服务器端发送一个 FIN 包,服务器收到之后执行被动关闭,这时候整个链路处于半关闭状态,此后,服务器端也会执行 close 函数,整个链路才会真正关闭。半关闭的状态下,发起 close 请求的一方在没有收到对方 FIN 包之前都认为连接是正常的;而在全关闭的状态下,双方都感知连接已经关闭。
套接字地址格式
套接字的通用地址结构
/* POSIX.1g 规范规定了地址族为2字节的值. */
typedef unsigned short int sa_family_t;
/* 描述通用套接字地址 */
struct sockaddr{
sa_family_t sa_family; /* 地址族. 16-bit*/
char sa_data[14]; /* 具体的地址值 112-bit */
};
地址族在 glibc 里的定义非常多,常用的有以下几种:
AF_LOCAL:或者AF_UNIX、AF_FILE,表示的是本地地址;
AF_INET:因特网使用的 IPv4 地址;
AF_INET6:因特网使用的 IPv6 地址。
AF_ 表示的含义是 Address Family,但是很多情况下,我们也会看到以 PF_ 表示的宏,比如 PF_INET、PF_INET6 等,实际上 PF_ 的意思是 Protocol Family,也就是协议族的意思。AF_INET和PF_INET,这两个值本身就是一一对应的
IPv4 套接字格式地址
/* IPV4套接字地址,32bit值. */
typedef uint32_t in_addr_t;
struct in_addr
{
in_addr_t s_addr;
};
/* 描述IPV4的套接字地址格式 */
struct sockaddr_in
{
sa_family_t sin_family; /* 16-bit */
in_port_t sin_port; /* 端口号 16-bit*/
struct in_addr sin_addr; /* Internet address. 32-bit */
/* 这里仅仅用作占位符,不做实际用处 */
unsigned char sin_zero[8];
};
IPv6 套接字地址格式
struct sockaddr_in6
{
sa_family_t sin6_family; /* 16-bit */
in_port_t sin6_port; /* 传输端口号 # 16-bit */
uint32_t ; /* IPv6流控信息 32-bit*/
struct in6_addr sin6_addr; /* IPv6地址128-bit */
uint32_t sin6_scope_id; /* IPv6域ID 32-bit */
};
几种套接字地址格式比较
IP地址和端口号总是以网络字节顺序(大端法)存放的
connect、bind 和 accept函数要求一个指向与协议相关的套接字地址结构的指针。
应用程序将与协议特定的结构的指针强制转换成通用结构
sockaddr in 结构强制转换成通用 sockaddr 结构
为什么要强制转换?
我的理解是IPV4,IPV6是网络协议规定的,如果没有通用结构,需要对这两种协议都要进行实现,耦合性太强且实现重复逻辑多。
而用一个通用的结构抽象了所有可变的因素,优点类似与Java接口的感觉
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?