前言(认识TCP/UDP报文格式)
字段名称位数说明源端口(Source Port)16 位发送方端口号目的端口(Destination Port)16 位接收方端口号UDP 长度(Length)16 位UDP 头 + 数据总长度校验和(Checksum)16 位检测错误数据(Data)可变实际传输内容
字段名称位数说明源端口(Source Port)16 位发送方端口号目的端口(Destination Port)16 位接收方端口号序列号(Sequence Number)32 位用于分片排序、可靠传输确认号(Acknowledgment Number)32 位用于确认收到的数据首部长度(Header Length)4 位TCP 头部长度保留字段(Reserved)6 位保留未用标志位(Flags)6 位URG、ACK、PSH、RST、SYN、FIN窗口大小(Window Size)16 位流量控制校验和(Checksum)16 位错误检测紧急指针(Urgent Pointer)16 位URG 数据偏移选项(Options)可变可选字段,如 MSS、窗口扩大等数据(Data)可变实际传输内容1.TCP/IP基础概念1.1TCP是什么?TCP(Transmission Control Protocol,传输控制协议)是一种 面向连接、可靠、有序 的传输协议。
✅ 核心特点:
面向连接:通信前必须先“握手”建立连接(三次握手),结束后要“挥手”断开(四次挥手)。
可靠传输:确保数据不丢失、不重复、按顺序到达。如果丢包,会自动重传。
流量控制 & 拥塞控制:防止发送太快导致接收方或网络崩溃。
字节流服务:应用层发的数据被看作连续的字节流,没有消息边界。
举个例子:
当你用浏览器打开一个网页(比如百度),背后就是通过 TCP 下载网页内容——必须保证每一张图片、每一行文字都完整无误地传到你电脑上。
常见用途:
网页浏览(HTTP/HTTPS)
电子邮件(SMTP、IMAP)
文件传输(FTP)
数据库连接
✅ 适合对“准确性”要求高的场景。
1.2TCP的报文格式及说明1.3UDP 是什么?UDP(User Datagram Protocol,用户数据报协议)是一种 无连接、不可靠、高效 的传输协议。
✅ 核心特点:
无连接:不需要建立连接,直接发送数据。
不可靠:不保证数据一定到达,也不重传、不排序。
低延迟、高效率:头部只有 8 字节,处理快,适合实时通信。
保留消息边界:每次发送就是一个独立的数据包(“数据报”)。
举个例子:
你在玩《王者荣耀》时,你的操作(比如移动、释放技能)通过 UDP 发送给服务器。即使偶尔丢掉一个操作包,游戏也能继续,但若用 TCP 等待重传,就会明显卡顿。
常见用途:
视频会议(Zoom、腾讯会议)
在线游戏
直播(如抖音直播、B站直播)
DNS 域名查询
物联网(IoT)设备通信
✅ 适合对“速度”和“实时性”要求高、能容忍少量丢包的场景。
1.4UDP的报文格式及说明2.TCP和UDP的核心区别对比项TCPUDP连接方式面向连接(建立连接后传输)无连接(直接发包)可靠性可靠传输:确认应答、重传机制不可靠传输:不保证送达顺序性保证数据包按顺序到达不保证顺序传输速度相对较慢(处理机制多)非常快(协议更轻量)传输模式字节流(Stream)数据报(Datagram)头部开销较大(至少 20 字节)很小(8 字节)流量控制支持(滑动窗口)不支持拥塞控制支持(慢启动、拥塞避免等)不支持错误检测有校验+重传仅校验,无重传适用场景文件传输、HTTP、邮件、SSH 等可靠性高的应用视频直播、语音通话、DNS、实时游戏等实时性要求高的应用是否有握手/挥手有:三次握手、四次挥手无:直接发送数据边界无边界(连续字节流)有边界(按数据包发送)3. TCP 的关键机制(重点)3.1三次握手(Three-Way Handshake) 握手过程
TCP 是面向连接的协议,通信前必须建立连接。三次握手确保双方都能正常收发数据。
步骤发送方 → 接收方标志位说明1客户端 → 服务端SYN=1, seq=x客户端发起连接请求,随机初始序号 x2服务端 → 客户端SYN=1, ACK=1, seq=y, ack=x+1服务端确认客户端请求,并发送自己的初始序号 y3客户端 → 服务端ACK=1, seq=x+1, ack=y+1客户端确认服务端的 SYN,连接建立完成✅ 此后双方进入 ESTABLISHED 状态,可正常传输数据。
❓ 为什么需要“三次”?两次行不行?核心原因:防止历史重复连接请求造成资源浪费或错误连接。
假设只有两次握手:
客户端发送 SYN,但因网络延迟很久才到达服务端;此时客户端早已超时重发或放弃;服务端收到“过期”的 SYN,误以为是新连接,直接分配资源并回复 ACK;但客户端不会响应(因为它没发起新连接),导致服务端白白占用资源。三次握手解决了这个问题:
第三次 ACK 由客户端发出,表明它确实想建立连接;如果是旧 SYN,客户端不会发第三次 ACK,服务端就不会真正建立连接。✅ 三次握手能双向确认双方的发送和接收能力都正常,且避免历史连接干扰。
3.2四次挥手(Four-Way Wavehand / Connection Termination)TCP 连接是全双工的(双方可同时收发),所以关闭需要各自独立关闭方向。
挥手过程
步骤发送方 → 接收方标志位说明1主动关闭方 → 被动方FIN=1, seq=u主动方(如客户端)数据发送完,请求关闭2被动方 → 主动方ACK=1, seq=v, ack=u+1被动方确认 FIN,但可能还有数据要发3被动方 → 主动方FIN=1, seq=w, ack=u+1被动方数据也发完,请求关闭4主动方 → 被动方ACK=1, seq=u+1, ack=w+1主动方确认,连接完全关闭 注意:步骤 2 和 3 不能合并(除非被动方恰好没有数据要发),所以通常是四次。
⏳ 为什么有 TIME_WAIT 状态?
主动关闭方在发送最后一个 ACK 后,会进入 TIME_WAIT 状态,持续 2×MSL(Maximum Segment Lifetime,通常 30~120 秒)。
目的有两个:
确保最后一个 ACK 能到达对方如果 ACK 丢失,被动方会重发 FIN;TIME_WAIT 期间可再次响应 ACK,避免对方无法关闭。防止旧连接的数据包干扰新连接网络中可能还有旧连接的“残余数据包”;等待 2×MSL(足够让所有旧包过期),再允许相同四元组(IP+端口)建立新连接。⚠️ 大量短连接可能导致服务器 TIME_WAIT 过多,占用端口资源(可通过 SO_REUSEADDR 优化)。
3.3滑动窗口(Sliding Window)—— 实现流量控制 目标:防止发送方发得太快,导致接收方缓冲区溢出。 工作原理:
接收方在每个 ACK 报文中携带 窗口大小(Window Size) 字段,告诉发送方“我还能接收多少字节”。发送方根据这个窗口动态调整可发送的数据量。窗口“滑动”:随着数据被确认,窗口向前移动,释放新空间。示例:
接收方缓冲区 4KB,已用 1KB → 告诉发送方窗口 = 3KB;发送方最多发 3KB 数据,直到收到新的 ACK 更新窗口。✅ 滑动窗口实现了端到端的流量控制(Flow Control),保护接收方不被压垮。
3.4拥塞控制(Congestion Control)目标:防止网络过载(不只是接收方,而是整个路径上的路由器/链路)。
TCP 使用 四个核心算法:
1. 慢启动(Slow Start)
初始拥塞窗口(cwnd)很小(如 1 MSS);每收到一个 ACK,cwnd += 1 MSS → 指数增长(1→2→4→8…);直到达到 慢启动阈值(ssthresh),转为拥塞避免。 快速探测网络容量,但避免一开始就发太多。2. 拥塞避免(Congestion Avoidance)
cwnd 线性增长:每 RTT 增加 1 MSS(即每个 ACK 增加 1/cwnd);更温和地探测网络上限。3. 快速重传(Fast Retransmit)当发送方收到 3 个重复 ACK(表示某个包丢失,后续包已到);不等超时,立即重传丢失的包;避免长时间等待 RTO(Retransmission Timeout)。4.快速恢复(Fast Recovery)在快速重传后进入;将 ssthresh 设为当前 cwnd 的一半;cwnd = ssthresh + 3(补偿已收到的重复 ACK 数量);继续按拥塞避免方式增长,不回到慢启动。 整体策略:
慢启动 → 拥塞避免 →(丢包)→ 快速重传 + 快速恢复 → 拥塞避免
3.5超时重传(Retransmission Timeout, RTO) 触发条件:
发送数据后,在 RTO 时间内未收到 ACK;则认为包丢失,重传该数据段。⏱️ RTO 如何计算?
基于 RTT(Round-Trip Time) 动态估算;
使用 Jacobson 算法(考虑 RTT 变化和抖动);
公式简化版:
RTO = SRTT + 4 × RTTVAR
其中 SRTT 是平滑 RTT,RTTVAR 是 RTT 方差。
⚠️ 超时重传 vs 快速重传:
机制触发条件速度效率超时重传RTO 超时慢(秒级)低(网络空闲)快速重传收到 3 个重复 ACK快(毫秒级)高✅ 现代 TCP 优先使用快速重传,超时重传是最后兜底。
3.6 TCP 连接建立(三次握手)与关闭(四次挥手)状态变化表和说明表✅ TCP 连接建立(三次握手)与关闭(四次挥手)状态变化表
阶段步骤客户端(主动方)状态含义服务端(被动方)状态含义连接建立初始CLOSED无连接CLOSED无连接(三次握手)1. 客户端发 SYNSYN_SENT已发送 SYN,等待服务端确认LISTEN监听连接请求2. 服务端回 SYN+ACKSYN_SENT等待服务端 ACKSYN_RECEIVED已收到 SYN 并回 ACK,等待客户端最终确认3. 客户端发 ACKESTABLISHED连接已建立,可收发数据ESTABLISHED连接已建立,可收发数据数据传输—ESTABLISHED正常通信中ESTABLISHED正常通信中连接关闭1. 客户端发 FINFIN_WAIT_1已发送 FIN,等待 ACKESTABLISHED → CLOSE_WAIT收到 FIN,进入半关闭状态(仍可发数据)(四次挥手)2. 服务端回 ACKFIN_WAIT_2已收到 ACK,等待服务端 FINCLOSE_WAIT应用层需调用 close() 才能发 FIN3. 服务端发 FINFIN_WAIT_2等待服务端 FINLAST_ACK已发送 FIN,等待客户端确认 ACK4. 客户端发 ACKTIME_WAIT等待 2×MSL 后彻底关闭CLOSED连接完全关闭超时后CLOSED连接彻底释放—— 关键状态详解
状态说明LISTEN服务端等待客户端连接请求(调用 listen() 后)SYN_SENT客户端已发送 SYN,等待服务端响应SYN_RECEIVED服务端收到 SYN 并回复 SYN+ACK,等待客户端 ACK(短暂中间态)ESTABLISHED连接已建立,双方可正常收发数据FIN_WAIT_1主动关闭方已发送 FIN,等待对方 ACKFIN_WAIT_2主动关闭方已收到 ACK,等待对方 FIN(此时不能再发送数据,但可接收)CLOSE_WAIT被动关闭方收到 FIN,通知应用层关闭连接,等待本地应用调用 close()LAST_ACK被动关闭方已发送 FIN,等待最后 ACK,收到后关闭TIME_WAIT主动关闭方确保最后一个 ACK 被接收,并防止旧连接影响新连接(等待 2×MSL)CLOSED无连接或连接已完全释放 补充说明
** 谁先发 FIN,谁就是主动关闭方(通常是客户端,但服务端也可主动关闭)。**** TIME_WAIT 只出现在主动关闭方。**如果服务端主动关闭,则角色互换,状态变化对称。大量 TIME_WAIT 是正常现象,但过多可能耗尽端口(可通过调整内核参数优化)。3.7 总结图(逻辑流程)
连接建立: 三次握手
↓
数据传输: 滑动窗口(流量控制)
↓
拥塞控制(慢启动 → 拥塞避免)
↘ 丢包? → 快速重传 + 快速恢复
↘ 超时? → 超时重传 + 慢启动重启
↓
连接关闭: 四次挥手 + TIME_WAIT
4. UDP 的核心优势优势说明头部结构简单仅 8 字节 固定头部(TCP 至少 20 字节),开销极小无连接无需握手/挥手,直接发送数据,延迟极低无重传/确认机制不因丢包而阻塞或重传,避免卡顿保留消息边界每次 send() 对应一个独立数据报,应用层易处理支持广播/多播可同时向多个主机发送(TCP 仅支持单播)⚠️ 注意:这些“优势”本质上是牺牲可靠性换来的效率,适用于能容忍少量丢包的场景。
5. 实际应用场景对比协议类型常见应用场景示例/说明TCPWeb 通信HTTP / HTTPS(网页加载、API 请求)远程登录SSH(安全远程管理服务器)文件传输FTP(可靠传输文件)邮件服务SMTP / IMAP / POP3(邮件发送与收取)其他需要可靠性保障的通信数据必须可靠、有序,不丢不重UDP域名解析DNS(快速查询,无需建立连接)地址分配DHCP(广播式发现与响应)实时视频/音频传输RTSP、实时直播(低延迟比可靠性更重要)游戏通信FPS、MOBA(快速同步位置、状态)其他实时性要求高的应用即使丢包也要优先保证低延迟6.如何选择 TCP 或 UDP需求/场景推荐协议原因说明需要可靠传输TCP有重传、确认、丢包恢复需要实时性UDP无握手、无阻塞,延迟极低需要保证消息顺序TCP内部按序号保证严格的包顺序要极低延迟UDP不确认、不重传,发送即走允许少量丢包UDP丢包不阻塞,适用音视频/游戏不能接受丢包TCP保证可靠、有序