网络(五)|别再死背三次握手!一文吃透 TCP 全底层原理
传输层前言传输层UDP VS TCP四大核心特性对比端口号详解UDP协议深度解析UDP报文头部格式UDP 64KB 上限痛点校验和Checksum作用UDP 四大核心特点基于UDP的经典应用层协议TCP 协议深度解析TCP 报文头部格式TCP 四大核心特性TCP 可靠传输核心机制确认应答ACK—— 最核心机制超时重传 —— 解决丢包问题连接管理 —— 建立连接断开连接TCP 的三次握手TCP 的四次挥手滑动窗口流量控制拥塞控制延时应答捎带应答面向字节流UDP 与 TCP 取舍总结前言上一篇我们完整梳理了网络层核心知识明白了 IP 地址、路由、NAT 如何实现跨主机、跨网段的数据包转发网络层仅能把数据送达目标主机。但一台设备上会同时运行浏览器、服务端程序、数据库等多个进程只依靠 IP 无法精准区分数据该交给哪一个程序处理这就需要传输层完成端到端进程通信。本篇为后端面试最高频重难点完整覆盖两大核心协议 UDP、TCP包含端口作用、TCP 报文结构、三次握手 / 四次挥手、可靠传输机制、流量 / 拥塞控制、粘包拆包等必考内容。承接网络层 “主机寻址”延伸到传输层 “进程寻址”为后续应用层 HTTP、Socket 网络编程打下核心理论基础。传输层网络层只负责把包送到目标主机传输层负责精准送到主机里对应的进程提供端到端通信。两个核心协议TCP、UDP。UDP VS TCP四大核心特性对比特性UDPTCP连接属性无连接有连接三次握手建立连接传输可靠性不可靠传输可靠传输传输单位面向数据报DatagramPacket面向字节流通信模式全双工全双工端口号详解端口号是区分一台主机上不同应用程序的标识固定为2字节16位取值范围为0-65535。服务器必须手动指定固定端口号客户端通过IP固定端口访问服务客户端由操作系统自动分配随机空闲端口无需手动指定端口分段11-1023知名端口号系统预留绑定知名服务22 SSH、80 HTTP、443 HTTPS21024-65535普通端口号业务开发自定义端口。注意80 只是 HTTP 协议建议端口不是强制端口开发时务必保证自定义端口不被其他程序占用。UDP协议深度解析UDP报文头部格式UDP 报文 8字节固定头部应用层载荷数据头部分为4段每段2字节源端口号目的端口号UDP 报文总长度头部载荷UDP 校验和checksum。源IP、目的IP不属于UDP头部存储在下层网络层IP协议头部报文长度16位最大值65535因此单个UDP数据包最大只能携带64KB数据。UDP 64KB 上限痛点网页、大文件等场景下业务数据很容易超过 64KB方案一手动拆分数据包、接收端重组开发和测试成本极高方案二直接改用 TCPTCP 没有单包大小限制。校验和Checksum作用网络传输会受电磁干扰、线路波动出现比特翻转、数据错乱校验和用来校验数据是否传输出错。校验和本质上也是一个字符串体积比原始数据更小又是通过原始的数据生成的原始数据相同得到的校验和就一定相同校验和相同原始数据大概率相同。如何基于校验和来完成数据校验呢发送方根据原始数据data1通过算法计算出校验和发送方同时把原始数据 data1 校验和 checksum1 一起通过网络发送出去接收方用相同算法、重新根据收到的数据data2 checksum1计算新校验和 checksum2对比新旧校验和不一致代表数据损坏直接丢弃数据包一致代表大概率传输正常。计算校验和的算法有哪些?CRC 循环冗余算法UDP 默认使用存在哈希碰撞不同数据可能算出相同 CRC把当前要计算校验和的数据每个字节都进行累加把结果保存到这个两个字节的变量中累加过程若发生溢出也无妨若中间某个数据出现传输错误第二次计算的校验和会和第一次不同。MD5/SHA 哈希算法1定长输出无论原始数据多长计算得到的 MD5 结果固定16字节2雪崩效应原始数据只有1bit不同最终哈希值差异巨大3不可逆无法通过哈希值反推原始数据常用于密码加密、数据完整性校验。UDP 四大核心特点无连接协议本身不记录对端地址每次发送数据包都必须手动携带目标IP端口不可靠传输没有重传、确认机制丢包、乱序都不会处理面向数据报以完整 DatagramPacket 数据报为最小传输单位不会拆分、拼接全双工同一个 DatagramSocket 对象既可以调用 send 发送也可以调用 receive 接收。基于UDP的经典应用层协议DNS域名解析协议DHCP动态主机配置协议自动分配 IP 地址TFTP简单文件传输协议NFS网络文件系统BOOTP无盘设备启动协议。TCP 协议深度解析TCP 报文头部格式TCP 报文 可变头部 载荷数据头部最小20字节最大60字节多出的40字节属于选项字段核心字段16位源端口、16位目的端口、32位序号、32位确认序号、6个标志位、窗口大小、16位校验和等。TCP 四大核心特性有连接通信前通过三次握手建立专属连接通信结束四次挥手断开连接可靠传输保证数据不丢失、不乱序、不重复面向字节流把所有数据当作连续字节流处理没有数据包边界全双工一条连接可同时双向收发数据。TCP 可靠传输核心机制确认应答ACK—— 最核心机制发送方把数据发给接收方之后接收方收到数据就会给发送方返回一个应答报文acknowledgeACK 的确认序号 收到数据最后一个字节序号 1此时发送方收到这个应答报文就能够知道自己的数据是否发送成功。由于不同的数据包可能会走不同的路线实际中网络传输数据还可能会出现“后发先至”的情况。TCP 在此处要完成两个工作确保应答报文和发出去的数据能对上号不要出现歧义确保在出现“后发先至”现象时能够让应用程序仍然按照正确的顺序来理解数据依靠32位序号32位确认序号描述数据的先后顺序。如何区分一个数据包是普通的数据包还是应答数据包URGACKPSHRSTSYNFIN有六个标志位判断应答包只看ACK位ACK1代表当前报文是应答报文此时该数据包中的“确认序号字段”生效。TCP是如何保证可靠传输的TCP以确认应答为基础配合超时重传、快速重传、序号去重等一系列机制共同实现可靠传输。超时重传 —— 解决丢包问题丢包若数据包太多就会在路由器/交换机上出现“堵车”而路由器针对这一现象的处理就是把积压的数据包中的大部分之间丢弃掉。网络拥堵、线路故障会引发数据包丢失分为两种场景发送的数据包本身丢了接收方返回的ACK应答报文丢了。两种情况都会导致发送方超时没有收到ACK触发超时重传发送方发送数据后开启等待计时器超时前收到ACK重置计时器超时未收到ACK立刻重传当前数据包。超时等待时间动态变化每次超时重传等待时间都会翻倍多次重传依旧失败判定网络严重故障触发 TCP 连接重置代价可靠传输牺牲了一部分传输效率这也是 UDP 无法被 TCP 完全取代的原因。接收缓冲区不仅仅能够进行去重还能进行重新排序。确保发送的顺序和应用程序读取的顺序是一致的。连接管理 —— 建立连接断开连接建立连接就是三次握手的过程。断开连接就是四次挥手的过程。TCP此处的握手就是给对方传输一个简短的、没有业务数据的数据包通过这个数据包先唤醒对方的注意再进行后续操作。TCP 的三次握手TCP 在建立连接过程中需要通信双方一共握手三次才能完成连接的建立。实际开发中主动发起的一方就是“客户端”被动接受的一方就是“服务器”。建立连接的过程其实是通信双方都要给对方发起SYN也要给对方反馈ACK。TCP初心是为了实现可靠传输能够进行确认应答和超时重传有个前提当前网络应该是基本可用的、通畅的。三次握手的核心作用确认当前网络是否通畅要让发送方和接收方都能确认自己的发送能力和接收能力的正常1A发送SYN2B发送ACK和SYN此时B确定A的发送能力以及自己的接收能力正常3A发送ACK此时A确定自己以及B的发送能力和接收能力均正常发送ACK告知B。三次握手很重要四次握手也可以但没必要二次握手不可以达不到要求。让通信双方在握手过程中针对一些重要的参数进行协商。TCP通信过程中的序号从几开始就是双方协商出来的。每次建立连接时都会协商出一个和上次不一样的值。TCP的两个重要状态LISTEN服务器端的状态。服务器Socket创建好并并把端口号绑定好进入LISTEN状态允许客户端随时来建立连接。ESTABLISHED客户端、服务器都会有的状态。连接建立完成接下来可以进行正常通信了。TCP 的四次挥手建立连接一般是客户端主动发起的断开连接客户端和服务器都可以主动发起。连接断开也就是A和B把对端的信息删掉。FIN会在Socket对象close时被发起手动调用close方法、进程结束。注意此处B端的ACK和FIN通常不能合并因为两者之间的时间差不能确定而TCP还有一个延时应答机制能够拖延ACK的回应时间延时应答的时间窗口恰好合适时可以合并为三次挥手。TCP的两个重要状态CLOSED连接已经彻底断开可以释放。TIME_WAIT哪一方主动断开连接哪一方就会进入TIME_WAIT状态等待时长为 2MSL目的是为了防止最后一个ACK丢失。在上图的过程中A端会进入TIME_WAIT状态。以上的三个机制都是在保证TCP的可靠传输。滑动窗口滑动窗口是为了提高TCP的传输效率。TCP的可靠传输是会影响传输效率的。 引入可靠性的TCP的效率不可能超过无可靠性的UDP。滑动窗口缩短确认应答的等待时间。滑动窗口的滑动机制从图中不难看出窗口越大等待的ACK越多传输效率就越高。但上述滑动窗口出现了丢包怎么办ACK丢了不需要任何重传只需看确认序号当前序号之前的数据已经确认收到了下一个应该从确认序号这里继续发送。若ACK全丢了丢包率就是100%。数据包丢了上述重传过程是哪个数据丢了就重传哪个没丢的数据不需要重传。快速重传该重传机制就是快速重传滑动窗口只是发送模式本身不提供重传能力那滑动窗口是设置的越大越好吗不是。若传输的速度太快接收方就会处理不过来会出现丢包发送方还要重传。通信双方传输的数据量比较小也不频繁时使用普通的确认应答机制超时重传。通信双方传输的数据量比较大比较频繁时使用滑动窗口快速重传。流量控制流量控制就是站在接收方的角度反向制约发送方的传输速率。发送方发送的速率不应该超过接收方的处理能力。发送发送的数据会先到达接收方的接收缓冲区接收方从接收缓冲区中读取数据。通过接收方缓冲区剩余空间的大小来作为衡量处理能力的指标。接收方每次收到数据之后都会把接收缓冲区剩余空间的大小通过ACK返回给发送方。当接收方的缓冲区满了发送方会暂停发送数据但会周期性发送一个“窗口探测包”并不携带具体的业务数据只是为了触发ACK查询当前接收方的接收缓冲区剩余空间的大小。拥塞控制整个通信的路径也会影响传输效率。中间的转发过程中任意一个节点的处理能力达到上限都可能对发送方产生影响都可能会影响可靠传输。因此还需要衡量通信过程中的中间节点情况。接收方的处理能力很方便进行量化通过接收缓冲区空间剩余大小但中间节点结构很复杂因此可以通过“实验”找到一个合适的值。“实验”过程把中间节点视为一个整体发送发首先按照比较低的速度发送数据小窗口若传输过程很顺利没有出现丢包现象就尝试使用更大的窗口、更高的速度进行数据传输。如此反复随着窗口大小不停增大达到一定程度可能中间节点就会有一些达到最大限度此时该节点会出现丢包现象发送方若发现丢包现象出现了就把窗口大小调整小一点此时若继续丢包就继续缩小若未丢包就继续变大。在整个过程中发送方不停调整窗口大小逐渐达成“动态平衡”。刚开始会发送的很慢慢开始/慢启动一开始是指数增长增长到阈值就会变为线性增长到一定程度就会出现丢包一旦触发丢包就把窗口大小缩小重新开始并且根据当前丢包的窗口大小指定一个新的线性增长阈值。慢开始出现丢包后缩小窗口重新进行慢开始 - 指数增长 - 线性增长。快恢复出现丢包后缩小窗口到新阈值跳过指数增长过程直接开始线性增长。流量控制和拥塞控制都在限制发送方的发送窗口大小最终取两者的最小值。延时应答延时应答是为了提升传输效率。发送方的窗口大小是传输效率的关键。延时返回ACK给接收方更多的时间来读取接收缓冲区的数据。此时接收方读取了更多的数据之后缓冲区就有了更大的剩余空间返回的窗口大小也就变大了。捎带应答捎带应答就是在延时应答的基础上进一步提高效率。网络通信中往往是“一问一答”通信模型。面向字节流面向字节流的机制都会有一情况粘包问题。若同时有多个应用层数据包被传输过去此时就容易出现粘包问题。像UDP这种面向数据报的通信方式就没有上述问题。UDP接收缓冲区中是一个个DatagramPacket对象。如何解决粘包问题核心思路通过定义好应用层协议明确应用层数据包之间的边界。 引入分隔符(比如aaa\n、bbb\n)或引入长度(比如3aaa、3bbb)。UDP 与 TCP 取舍总结TCP 适用场景文件下载、网页浏览、数据库交互、支付业务。场景要求数据绝对完整丢失数据包必须重传补齐。UDP 适用场景直播、语音通话、游戏对战、实时视频。这类场景允许少量丢包优先降低延迟、保证传输速度如需可靠性需要上层应用自己实现重传逻辑。到此传输层 TCP 与 UDP 的核心原理就讲解完毕。传输层向下依托网络层完成主机转发向上为应用层提供进程通信能力。下一篇我们将进入应用层详解 HTTP 与 HTTPS 协议。本篇是「Java后端编程系列」的连载内容点击链接查看完整系列 上一篇网络四全网最细网络层原理IP 协议、IP 地址分类、子网划分、路由转发、NAT 穿透详解 点击直达 Java后端基础专栏合集