🎯 核心定位与四大特性
面向连接:通信前必须建立连接,通信后断开连接
点对点:只能是一对一通信(不支持广播/多播)
可靠交付:无差错、不丢失、不重复、按序到达
全双工通信:双方可同时发送和接收数据,独立关闭通道
🔗 连接管理:三次握手 (建立连接)
详细交互流程
第 1 次:Client -> Server [SYN=1, seq=x] -> Client 进入 SYN_SENT
第 2 次:Server -> Client [SYN=1, ACK=1, seq=y, ack=x+1] -> Server 进入 SYN_RCVD
第 3 次:Client -> Server [ACK=1, seq=x+1, ack=y+1] -> 双方进入 ESTABLISHED
💡 核心设计目的
同步双方初始序列号 (ISN),为后续可靠传输做准备
确认双方的发送能力和接收能力均正常
❓ 深度思考:为什么必须是三次?
防止历史失效连接请求突然到达服务端,导致服务端错误建立连接并浪费资源
两次握手无法防止客户端连接初始化失败导致的资源浪费
🛡️ 安全威胁:SYN Flood 攻击
原理:恶意客户端发送大量 SYN 报文,不回复第三次 ACK
后果:耗尽服务端半连接队列 (SYN Queue) 资源,拒绝服务
防御手段:SYN Cookie 技术 / 缩短 SYN 超时时间 / 防火墙限流/黑名单
🚪 连接管理:四次挥手 (断开连接)
详细交互流程
第 1 次:Client -> Server [FIN=1, seq=u] -> Client 进入 FIN_WAIT_1
第 2 次:Server -> Client [ACK=1, ack=u+1] -> Server 进入 CLOSE_WAIT,Client 进入 FIN_WAIT_2
第 3 次:Server -> Client [FIN=1, seq=w] -> Server 进入 LAST_ACK
第 4 次:Client -> Server [ACK=1, ack=w+1] -> Client 进入 TIME_WAIT,Server 进入 CLOSED
💡 核心设计目的
TCP 是全双工的,每个方向的关闭必须独立进行(所以是四次而不是三次)
确保双方数据都能发送/接收完毕(Server 收到 FIN 时可能还有数据没发完)
❓ 深度思考:为什么需要 TIME_WAIT (持续 2MSL)?
保证最后一个 ACK 能到达(若丢失,Server 会重发 FIN,Client 可重传 ACK)
等待网络中该连接的残余报文消失,防止新连接收到旧数据导致混乱
🚨 程序员实战排障:异常状态排查
大量 CLOSE_WAIT:服务端代码逻辑 Bug,收到 FIN 后未调用 close() 释放资源
大量 TIME_WAIT:短连接过多,频繁建连断连。解决:开启 tcp_tw_reuse、改用长连接池
🔄 TCP 状态机全景 (11 种核心状态)
客户端主导状态:CLOSED -> SYN_SENT -> ESTABLISHED -> FIN_WAIT_1 -> FIN_WAIT_2 -> TIME_WAIT -> CLOSED
服务端主导状态:LISTEN -> SYN_RCVD -> ESTABLISHED -> CLOSE_WAIT -> LAST_ACK -> CLOSED
🛡️ 可靠性保证机制 (核心算法拆解)
序号与确认应答 (Seq & ACK)
序号 (seq):字节流的编号,解决乱序问题
确认号 (ack):期望收到对方下一个报文段的第一个字节序号,解决丢包问题
超时重传机制
发送数据启动定时器,超时未收到 ACK 则重传
动态计算 RTO (重传超时时间):基于 RTT (往返时间) 的平滑加权移动平均计算
滑动窗口与流量控制 (端到端视角)
原理:接收方通过 TCP 首部 "窗口大小" 字段告知发送方自己的接收缓存剩余空间
零窗口探测:接收窗口为 0 时,发送方定期发送探测报文,防止死锁
糊涂窗口综合征:接收方缓存满时,发送方仍发送小数据。解决:Nagle 算法(延迟发送)、延迟确认
拥塞控制算法 (全局网络视角,防止网络瘫痪)
慢开始 (Slow Start):拥塞窗口 cwnd 指数增长,达到 ssthresh 后转为拥塞避免
拥塞避免 (Congestion Avoidance):cwnd 线性增长(每个 RTT 加 1),防止网络突然拥塞
快重传 (Fast Retransmit):收到 3 个重复 ACK,立即重传丢失报文,不等待超时
快恢复 (Fast Recovery):快重传后,ssthresh 减半,cwnd 设为新的 ssthresh,直接进入拥塞避免
📦 TCP 粘包/拆包问题 (应用层必考)
产生根本原因:TCP 是面向字节流的,没有消息边界
具体触发场景
粘包:应用层写入速度 > 网络发送速度(多个小包合并);发送报文 < MSS(TCP 优化机制)
拆包:应用层写入的大数据 > MSS(TCP 强制拆分)
经典解决方案
定长消息:每个报文固定长度(如固定 100 字节),不足补空
特殊分隔符:如 HTTP 的 \r\n,FTP 的换行符(不适合传输二进制数据)
长度字段 (Length Field):Header 中包含 Body 长度(最常用,如 RPC 框架、游戏协议)
高级序列化:Protobuf, JSON 结合长度头,自带边界解析
📊 TCP 报文首部关键字段 (20~60字节)
源/目的端口号 (各 16bit):标识应用进程,实现多路复用
序号/确认号 (各 32bit):可靠传输的核心
数据偏移 (4bit):指出 TCP 首部长度(以 4 字节为单位)
控制位 (6bit):URG(紧急), ACK(确认), PSH(推送), RST(重置), SYN(同步), FIN(终止)
窗口大小 (16bit):流量控制,配合窗口扩大选项可达 1GB
校验和 (16bit):校验首部和数据(需加上 12 字节的伪首部)
紧急指针 (16bit):配合 URG 标志,指出紧急数据末尾
选项 (Options):MSS(最大报文段长度)、窗口扩大因子、时间戳、SACK(选择确认)