传输层的重要协议UDP/TCP

UDP网络协议

学习网络协议,主要就是在学习协议格式

协议格式

  1. 源端口:两个字节,表示发送方的端口号
  2. 目的端口:两个字节:表示接收方的端口号
  3. 长度:表示数据包的总长度,单位为字节(一个数据报的最大长度就是64Kb)
  4. 校验和:验证UDP数据报是否在传输中出错

信号在传输过程中可能会发生比特翻转(0>1,1>0),导致数据出错,所以校验和就是用来甄别数据是否出错的有效方案,发送方会构造UDP数据报,构造完成之后,把数据报的每个字节的数据都进行累加,结果累加到一个16位的整数上,此时的结果就是校验和,填充到UDP报头的校验和字段,接收方收到数据报后,就会按照相同的算法再计算一遍,若相等,就说明数据传输正确

TCP网络协议

协议格式

  • 4位首部长度:表示报头的长度,最大长度是4*15=60个字节
  • 保留:6位字段,保留未来扩展
  • 控制位:URG是紧急指针有效,值为1时,指示紧急数据需优先处理;ACK为确认号有效,值为1时用于建立连接或数据确认;PSH为推送标志,值为1时,提示接收方立即将数据交付应用层;RST为重置连接,值为1时,强制断开异常连接;SYN为同步序列号,值为1时,用于发起连接请求;FIN表示结束连接,值为1时,表示数据发送完毕,请求关闭连接
  • 16位校验和:与UDP相同

特性:可靠传输

这里的可靠传输并不是指数据百分百到达,而是发送的数据,能够知道对方是否收到,就可以认为是可靠传输

核心机制一:确认应答(ACK)

实现让发送方知道接收方是否收到数据,发送方发了数据之后,接收方接收,一旦收到,就给发送方返回一个应答报文告诉对方已经收到

一系列的数据包传输过程中,不一定按照相同的路线转发,不同的路线可能到达的时间不同,为了解决上述问题,引入序号和确认序号对于传输的数据进行标识,编号是连续递增的,只要知道TCP载荷的第一个字节的编号是多少,之后每个字节的编号就都知道

确认序号只在应答报文中生效,ACK位为1确认序号才会有效,确认序号会根据收到数据的最后一个字节的序号+1进行填充,确认序号的含义:

1.所有小于确认序号的数据,接收方已经收到了

2.发送方接下来应该从确认序号位置继续发送数据

核心机制二:超时重传

作为确认应答的补充,实际中会发生丢包,如果发送方在预设时间(可配置)内未收到ACK,就会重新传输数据,随着传输次数的增加,数据报到达对方的概率大幅度增加

没有收到ACK有两种情况,一种是发送方未送达,丢包之后需要重传;另一种是接收方无法正确返回,这种情况下超时重传就会导致接收方收到重复数据,为了处理上述情况,TCP会在接收到数据的时候,在操作系统内核中维护一个"接收缓冲区",如果又收到了同一个数据,此时就可以根据数据的序号来在接收缓冲区进行"去重",确保应用程序在进行read操作的时候读到的数据都是唯一的;

数据在传输过程中很有可能出现"后发先至"的问题,TCP也会根据收到的数据在接收缓冲区进行重新排列,这样应用程序在读取数据的时候,读到的仍然是有顺序的数据

超时重传的超时时间不是固定的,而是动态变化的,随着超时重传的进行,如果还是没有收到ACK,就要继续重传,但是等待的超时时间会逐渐变长。重传次数和总的重传时间都存在上限,如果达到上限,重传还没有成功,TCP的连接就会被重置,也就是单方面的断开连接,重置会涉及到"复位报文"(RST),触发一次复位报文,意味着就要丢弃这个连接,就相当于删除掉之前保存的对方的信息。

总的来说,超时重传是TCP中进行可靠传输的重要机制之一,是确认应答的补充

核心性质三:连接管理

网络里的连接是虚拟的,抽象的连接,代表通信双方各自保存对方的关键信息(IP,端口等)建立连接是通过三次握手,断开连接是通过四次挥手

三次握手

TCP中的握手,是指传输一个"打招呼"的数据包,这个数据包不携带任何"业务数据",只有报头,没有正文,在建立连接过程中,客户端和服务器要经过三次这样的打招呼,连接才能在双方都建立

三次握手的关键流程如下:

  1. 客户端给服务器发起一个syn(同步报文段):客户端告诉服务器,我要和你建立连接,请你保存我的信息
  2. 服务器给客户端返回一个ack:服务器告诉客户端,收到,我会保存
  3. 服务器给客户端发起一个syn:我也要和你建立连接,请你保存我的信息
  4. 客户端收到之后,返回一个ack:客户端告诉服务器,收到,我会保存

从流程/逻辑上是四次交互,但是中间两次可以合并成一个TCP数据包,所以网络上实际只传输了三个数据包

三次握手的意义:

三次握手也可以视作一种"保证可靠传输的手段"(辅助手段)

  1. 三次握手,相当于"投石问路",验证通信链路是否畅通
  2. 三次握手,也是在验证通信双方发送和接收能力是否正常
  3. 通过三次握手,让通信双方协商关键信息

协商的关键信息指的是TCP数据的起始序号,TCP的序号是针对载荷部分按照字节编号,当TCP连接建立好了之后,传输的第一个数据包的第一个字节的编号不是从头开始的,而是在三次握手阶段协商出这样的数字,作为起始编号,每次建立连接,协商出来的起始编号都是不同的,这样设定的目的,为了避免出现网络传输中的特殊情况,每次重新建立连接都会重新协商出起始序号,看当前这个数据包的序号是不是很接近与当前连接的起始序号

三次握手之前服务器存在的状态为:LISTEN,进入这状态表示在监听这个端口,端口上一过来客户端,就能立马accept

三次握手之后状态转变为ESTABUSHED:客户端和服务器连接建立好了,客户端和服务器之间就可以进行通信了

四次挥手

四次挥手的关键流程如下:

  1. 客户端告诉服务器,我要和你断开连接,请你把我删除
  2. 服务器回应收到
  3. 服务器告诉客户端,我也要和你断开连接,请你把我也删了
  4. 客户端回应收到

客户端和服务器都会把对方的信息删除掉,删除完连接就断开了

和三次握手本质区别在于四次挥手不是完全由操作系统内核完成的,而是和应用层代码有关系

之所以叫做四次挥手,是因为中间两次交互,是不一定会触发合并的

1.不合并:

服务器收到FIN返回ack和close返回FIN如果不是同一时机,就会使两个数据无法合并

2.合并:

TCP有延时应答机制,应答ack的时机会往后拖一段时间,如果实际差不多就可以把两个数据合并

合并相比于不合并来说是更好的,合并能够提高效率

经典面试题:建立连接的时候,必须握手三次吗?两次?四次?

四次:可以,但是没必要,中间两次传输时机是相同的,合并成一次有利于提高效率

两次:不可以,无法完成通信双方发送能力,接受能力的验证

经典面试题:断开连接的时候,必须挥手四次吗?三次?

三次:可以

  • CLOSE_WAIT:被动断开连接的一方进入的状态,收到对方发来的FIN的时候,就会返回ACK,同时进入CLOSE_WAIT状态,可以理解成wait close,等待关闭,等待应用程序代码,调用close,正常情况下存在的时间会比较短,如果出现大量的此状态,很可能出现BUG
  • TIMED_WAIT:类似于线程中的TIMED_WAITING,是有时间限制的等待,等待连接彻底释放,按理说我方返回ACK就相当于四次挥手结束了,就可以释放连接了,但实际上并不能立即释放连接,而是要再等等,为了应对最后一个ACK丢包的情况,如果最后一个ACK丢包了,服务器会超时重传FIN回来,因此客户端就需要先等一段时间看对方是否会重传FIN,等待的时间为2*MSL(MSL指的是网络上任意两点之间,传输小号的最大时间)

核心性质四:滑动窗口

前面三个机制,是为了实现TCP的"可靠性";而滑动窗口是为了提高效率

每次发送一个数据,都要等ACK,单位时间内能传输的数据就少了,把每次发送都等待ACK优化为批量发送一波,等待一次ACK

等待一份的时间中,就是在等待4组ACK的到达,并且是收到一个ACK就立即往后发1组数据

滑动窗口机制下出现丢包:

情况一:数据包已经抵达,ACK被丢包,如果只是ACK被丢包,在滑动窗口机制下,不需要做任何处理,后一个ACK会自动涵盖前一个ACK,根据确认序号的设定规则,ACK的确认序号表示该序号之前的所有数据都已经收到。如果最后一个ACK丢失了,就会直接触发超时重传

情况二:数据包直接丢失,接收方会反复向发送方索要数据,发送方感知到接收方的多次索要后,就会认为这个数据包已经丢失,触发重传,一旦接收方收到了丢失的数据包,就会观察自己的接收缓冲区里的数据到哪了,就会从最后的数据继续索要(滑动窗口机制下的重传机制,相当于超时重传的变种)

TCP传输较大量数据的时候,自然就会触发滑动窗口,重传机制采取快速重传;如果传输较少的数据,此时就仍然按照确认应答和超时重传方式来进行

核心机制五:流量控制

流量控制是搭配滑动窗口使用的,滑动窗口越大,传输速度就越快,但是速度太快会对可靠性有影响,所以引入流量控制来根据接收方的处理能力,干预发送方的发送速度,及时调整滑动窗口的大小。接收方收到数据后会先加载到接收缓冲区里,可以把其想象成一个阻塞队列,如果队列里没有数据,应用程序就会在read的时候阻塞,直接衡量调用read的速度不太容易,所以使用接收缓冲区的剩余空间大小来衡量read的速度,以剩余空间大小反向制约发送方的发送速度,在接收方返回ACK报文的时候,在TCP报头中把接收缓冲区剩余空间大小的数值放到ACK的报头中,等发送方收到ACK就知道接收方的处理速度了,然后就可以根据窗口的大小来重新设置下一轮滑动窗口传输数据的窗口大小了

窗口大小一共有16位,是否意味着TCP的滑动窗口的大小最大只能是64KB,并不是,TCP设计的时候,选项中有一个窗口扩展因子,可以直接左移一位相当于×二倍

如果缓存区剩余空间大小为0了,发送方就会暂停发送,如果不暂停发送数据就会被丢弃,但是只是不发送业务数据,但是仍会周期性的发送窗口探测包,与此同时,接收方也会在接收区缓存不满的时候给发送方发送窗口更新包

核心机制六:拥塞控制

流量控制是考虑接收方的速率,还要考虑传输路径中所有中间节点的情况

拥塞控制的核心思路就是试试看,先按照比较小的速度发送数据,看是否丢包,如果丢包,说明有节点支持不住,就减小窗口大小,减小速度;反之则增大窗口大小,增加速度

所以发送方的发送窗口的大小取决于流量控制和拥塞控制的最小值,也就是接收方通过ACK告诉发送方的流量控制窗口和发送方自己维护一个变量作为拥塞控制的窗口

拥塞窗口的变化过程是以份为单位

1.初始情况下,窗口很小

2.慢启动之后如果不丢包,就以指数增长方式增长,短时间快速增长

3.指数增长到一定程度(达到阈值),指数增长变成线性增长

4.线性增长到一定程度,终究会触发丢包

5.1出现丢包,窗口大小一落千丈,从头再来一遍

5.2出现丢包,重新计算阈值,从阈值开始线性增长,使TCP的传输效率更稳定

核心机制七:延时应答

为了提高传输效率,承接滑动窗口,让窗口尽量大一些,不立即返回ACK,而是等接收方消费一会之后再返回,能使接收缓冲区的剩余空间大一些

上述模型生效的前提使延时应答的期间没有新的作业过来

核心机制八:捎带应答

服务器在收到客户端的请求后会返回ACK和响应,ACK中只有报头,没有载荷,报头中含有确认序号和窗口大小等;响应中又只是普通的响应报文,ACK位为0,确认序号和窗口大小这两位无效,正好给一次发送创造条件;同时,本来返回ACK的时机应该是收到请求之后立即返回,发挥响应的时机需要慢一些,但TCP会延时应答,所以两者正好赶上,就直接把ACK报文和响应数据做成一个TCP数据报返回

上述模型是基于延时应答的基础上,提高传输效率的方案

核心机制九:面向字节流

读取/写入数据的时候有很多操作方式,可能会造成粘包问题。粘包问题指的是收到多个TCP数据报的时候把所有的载荷都混到一起放在接收缓冲区中,包的边界就会模糊

接收方分用的时候,去掉报头,把载荷内容放到一个接收缓冲区中,接收方的应用程序在read的时候就有很多种read的可能性,那怎么才能确保读到的是一个完整的应用层数据包

  1. 通过特殊的分隔符来作为包边界的区分,当然要保证符号不会在正文中出现
  2. 在应用层数据包开头的地方,通过固定长度,约定整个应用层数据包的长度

粘包问题只针对字节流的传输

核心机制十:异常情况

1.进程崩溃

进程崩溃意味着对应的文件描述符就被关闭了(调用close),TCP的连接会保留一会,触发FIN

2.主机关机

触发FIN,进入四次挥手,可能会挥不完,但至少自己可以把保存的信息删除

3.主机掉电

来不及发起FIN,如果掉电的是接收方,对方会继续发送数据,触发超时重传,达到一定程度,发送方会发送一个复位报文,表示要重置连接,也就是放弃当前的连接;如果掉电的是发送方,接收方会继续阻塞等待,接收方会定期的和发送方交换心跳包,如果发现连心跳包也没有应答,就可以单方面的释放连接了

4.网线断开

本质上和主机掉电一样

用UDP实现可靠传输(经典面试题)

基于UDP在应用层参考TCP的做法(核心性质)

相关推荐
W说编程2 小时前
《UNIX网络编程卷1:套接字联网API》第8章:基本UDP套接字编程深度解析
网络·网络协议·tcp/ip·udp·unix·极限编程
cyforkk2 小时前
16、Java 基础硬核复习:网络编程的核心逻辑与面试考点
java·网络·面试
脑洞代码2 小时前
协议头部格式详解:IP、TCP、UDP与MAC帧结构
网络·笔记·学习
网络修理工2 小时前
如何高效采集Google地图数据的动态IP策略(2026数据爬虫实战)
网络·人工智能
weixin_443290692 小时前
【华为HCIA路由交换认证指南】第五章 静态路由
网络·华为·智能路由器
ZeroNews内网穿透2 小时前
本地搭建 Clawdbot + ZeroNews 访问
网络·安全·web安全·clawdbot
石去皿2 小时前
一款轻量级桌面级图片批量压缩工具,专为高效减小图片文件体积而设计,面向latex编译速度优化
网络·人工智能·工具·压缩图片
weixin_443290692 小时前
【华为HCIA路由交换认证指南】第六章 动态路由
网络·华为·智能路由器
有味道的男人2 小时前
接入MIC(中国制造)接口的帮助
网络·数据库·制造