第4章:传输层详解
传输层,说白了就是网络通信的「中间人」。
它夹在应用层和网络层之间,干的是最累的活——保证数据能准确、完整地送到对方手里。我做了这么多年网络,见过太多因为传输层没搞明白而翻车的案例。今天咱们就把TCP和UDP这两个核心协议彻底讲透。
4.1 TCP协议特性
TCP,全称传输控制协议。它最大的特点就一个字:稳。
你想想看,如果发一条消息过去,对方收没收到你都不知道,那还怎么玩?TCP就是来解决这个问题的。
TCP的核心特性:
- 面向连接:通信前必须先建立连接,通信完必须释放连接
- 可靠传输:保证数据不丢失、不重复、按序到达
- 流量控制:根据接收方能力调整发送速度
- 拥塞控制:根据网络状况动态调整发送速率
- 全双工通信:双方可以同时收发数据
我记得有一次排查线上问题,发现某个服务经常超时。查了半天,原来是TCP的拥塞控制算法在作怪——网络稍微有点波动,发送窗口就缩得特别小,导致数据卡在半路上。嗯,这里要注意,TCP的「可靠」是有代价的。
4.2 TCP报文结构
TCP报文长什么样?我习惯把它拆成两部分来看:头部和数据。
头部最少20字节,最多60字节。咱们重点看几个关键字段:
| 字段 | 长度 | 说明 |
|---|---|---|
| 源端口 | 16位 | 发送方的端口号 |
| 目的端口 | 16位 | 接收方的端口号 |
| 序列号 | 32位 | 本报文段数据的第一个字节序号 |
| 确认号 | 32位 | 期望收到的下一个字节的序号 |
| 数据偏移 | 4位 | 头部长度,单位是4字节 |
| 标志位 | 6位 | URG、ACK、PSH、RST、SYN、FIN |
| 窗口大小 | 16位 | 接收窗口,用于流量控制 |
| 校验和 | 16位 | 校验头部和数据部分 |
这里有个坑,我刚开始学的时候总搞混序列号和确认号。说白了,序列号是告诉对方「我发到哪了」,确认号是告诉对方「你发到哪了,下一个该发啥」。
小技巧:抓包的时候,重点关注SYN、ACK、FIN这三个标志位。三次握手和四次挥手全靠它们来识别。
4.3 三次握手
三次握手,就是建立TCP连接的过程。为什么是三次?不是两次也不是四次?
我直接说结论:两次不够可靠,四次太浪费。三次刚刚好。
具体流程是这样的:
- 第一次握手:客户端发送SYN包,序列号设为x,进入SYN_SENT状态
- 第二次握手:服务器收到SYN,回复SYN+ACK包,确认号设为x+1,自己的序列号设为y,进入SYN_RCVD状态
- 第三次握手:客户端收到SYN+ACK,发送ACK包,确认号设为y+1,进入ESTABLISHED状态
服务器收到ACK后,也进入ESTABLISHED状态。连接建立完成。
注意:我曾经遇到过一个问题——客户端发完SYN后一直没收到SYN+ACK。查了半天,发现是防火墙把SYN包给丢了。所以排查连接问题时,别忘了检查中间设备。
三次握手的核心目的有两个:
- 确认双方的收发能力都正常
- 同步双方的初始序列号
你想想看,如果只有两次握手,服务器怎么知道客户端有没有收到自己的SYN+ACK?万一丢了,服务器还傻等着,那就出问题了。
4.4 四次挥手
四次挥手,就是断开TCP连接的过程。比握手多了一次,因为TCP是全双工的,每一路都需要单独关闭。
流程是这样的:
- 第一次挥手:客户端发送FIN包,序列号为u,进入FIN_WAIT_1状态
- 第二次挥手:服务器收到FIN,回复ACK包,确认号为u+1,进入CLOSE_WAIT状态
- 第三次挥手:服务器发送FIN包,序列号为v,进入LAST_ACK状态
- 第四次挥手:客户端收到FIN,回复ACK包,确认号为v+1,进入TIME_WAIT状态
客户端在TIME_WAIT状态要等2MSL(最大报文段生存时间)才能彻底关闭。为什么?
说白了,就是为了确保最后一个ACK能到达服务器。如果ACK丢了,服务器会重发FIN,客户端还能再回应一次。
避坑指南:我曾经在生产环境遇到过大量TIME_WAIT连接堆积的问题。原因是短连接太多,客户端频繁建立和断开连接。解决方案是改用长连接,或者调整系统参数缩短TIME_WAIT时间。
4.5 UDP协议特性
UDP,用户数据报协议。和TCP完全相反,它主打一个「快」字。
UDP的特点:
- 无连接:发数据前不需要建立连接
- 不可靠:不保证数据到达,不保证顺序
- 无流量控制:发多少算多少
- 无拥塞控制:网络堵了也不管
- 开销小:头部只有8字节
你可能会问:这么不靠谱的协议,有什么用?
我举个例子你就明白了——视频通话。你愿意为了等一帧画面而卡住整个视频吗?显然不愿意。丢几帧画面无所谓,但卡顿是不能忍的。这就是UDP的用武之地。
UDP报文结构更简单:
| 字段 | 长度 | 说明 |
|---|---|---|
| 源端口 | 16位 | 发送方的端口号 |
| 目的端口 | 16位 | 接收方的端口号 |
| 长度 | 16位 | UDP报文的总长度 |
| 校验和 | 16位 | 可选,不校验时填0 |
看到没?就4个字段,8个字节。比TCP的20字节头部轻量多了。
UDP的典型应用场景:
- DNS查询:发一个请求,等一个响应,丢了就重发
- 视频直播:允许少量丢包,追求低延迟
- 在线游戏:实时性要求高,丢包比延迟好
- 物联网:设备资源有限,UDP开销小
4.6 TCP vs UDP 对比
我习惯用一个表格来对比这两个协议,一目了然:
| 对比项 | TCP | UDP |
|---|---|---|
| 连接方式 | 面向连接 | 无连接 |
| 可靠性 | 可靠 | 不可靠 |
| 顺序保证 | 保证 | 不保证 |
| 流量控制 | 有 | 无 |
| 拥塞控制 | 有 | 无 |
| 头部大小 | 20-60字节 | 8字节 |
| 传输方式 | 字节流 | 数据报 |
| 典型应用 | HTTP、FTP、SMTP | DNS、视频、游戏 |
选哪个协议,说白了就看你的业务需求。要可靠就选TCP,要速度就选UDP。没有的好坏,只有合不合适。
我的建议:如果你不确定选哪个,默认用TCP。等发现性能瓶颈了,再考虑换成UDP或者基于UDP的自定义协议。别一开始就搞复杂了。
4.7 本章知识体系
下面这张图,把传输层的核心逻辑串起来了:
这张图把传输层的核心脉络理清楚了。TCP这边,重点掌握三次握手和四次挥手;UDP这边,记住它简单、快速、无状态就行。
好了,传输层的内容就讲到这里。下一章咱们进入应用层,看看HTTP协议到底是怎么工作的。
可可精品资料库