当前位置: 首页 > news >正文

26考研 | 王道 | 第五章 传输层

26考研 | 王道 | 第五章 传输层

文章目录

  • 26考研 | 王道 | 第五章 传输层
    • 1. 传输层提供的服务
    • 2. UDP协议
      • 2.1 UDP数据报
      • 2.2 UDP检验
        • IP首部检验和 与 UDP检验和的区别
    • 3.TCP协议
      • 3.0 TCP概览
        • 面向字节流和面向连接理解
      • 3.1 TCP段格式
      • 3.2 TCP连接管理
        • 1.三次握手
          • 1.考察SYN,ACK,FIN,seq,ack_seq
          • 2.进程TCP状态的转换
          • 3.耗时分析
        • 2.四次挥手
          • 1.各个数值
          • 2.进程TCP状态的转换
          • 3.耗时分析
      • 3.3 可靠传输和流量控制
        • 1.确认号、发送窗口接收窗口
        • 2.累积确认
        • 3.捎带确认
        • 4.超时重传
        • 5.快重传、立即确认
          • 1.推迟确认的缺点
          • 2.快重传、立即确认
          • 3.易错点
      • 3.4 拥塞控制
        • 1.慢开始、拥塞避免
        • 2.快重传、快恢复

1. 传输层提供的服务

IP报协议部分TCP是6,UDP是17

image-20250523115043385

image-20250523114543899

image-20250523114746705

image-20250523114812229

image-20250523115134254

image-20250523115233064

2. UDP协议

image-20250523120433117

2.1 UDP数据报

image-20250523115724973

image-20250523115750914

UDP数据报实际最大长度只有65515B这么长,因为IP数据报不拆分的最长长度也就是65535B这么长,还要除去至少20B的IP数据包首部长度,那么剩下的65515B就是UDP数据报的总长度了。

image-20250523120339933

2.2 UDP检验

image-20250523121140274

其实就是UDP对应的差错控制,错了直接扔了,而且不通知发送方

image-20250523120544969

接收方把数据和检验和相加如果得到的不是全1就是错的

image-20250523120712041

image-20250523120926418

刚开始的没有计算过检验和的时候,把检验和当做全0来算

IP首部检验和 与 UDP检验和的区别

两者检验方法一致,需注意一下区别

1.IP首部检验和只检查首部,不检查数据部分

2.IP首部检验和不需要添加伪首部

image-20250523121357220

3.TCP协议

3.0 TCP概览

TCP建立的连接本质上是两台主机的进程之间的通信,而非单纯的主机到主机的连接。

image-20250523121643503

建立连接由客户端发起,释放连接客户端和服务器都可以发起

image-20250523122054740

image-20250523122420277

MSS只是数据部分的大小,不包含首部长度

面向字节流和面向连接理解

面向字节流的理解:不管进程给了TCP多少报文,在它看来都是一连串的字节流,它要做的就是按照MSS把这个字节流拆分开来,然后通通交给接收进程的TCP

TCP与UDP在数据传输方式上的核心差异体现在面向字节流面向报文的特性上。

  1. TCP的字节流特性
    TCP将应用层传递的数据视为无结构的连续字节序列,发送方会根据网络条件(如MTU限制)自动拆分或合并数据。例如,若应用程序连续发送"Hello"和"World",TCP可能将其合并为"HelloWorld"发送,接收方无法直接区分原始分界点。这种特性导致需要应用层通过特殊分隔符或自定义消息头解决"粘包"问题
  2. UDP的报文边界保留
    UDP严格保留应用层提交的消息完整性。每个UDP数据报(Datagram)都对应一个完整的用户消息,发送方既不拆分也不合并数据。例如,若应用层发送"Hello"和"World",接收方会收到两个独立的数据报,边界清晰。这种特性使UDP天然适合需要消息独立性的场景(如DNS查询)。
  • TCP发送过程
    应用层发送"123456789" → TCP拆分为3个段(“1234”、“5678”、“9”) → 接收方缓存重组为完整字节流
  • UDP发送过程
    应用层发送两个消息"A"和"B" → 生成两个独立数据报 → 接收方分别读取"A"和"B"

典型应用场景

  1. TCP适用场景
    • 需要数据完整性的场景:HTTP网页加载、电子邮件传输(SMTP/POP3)
    • 长连接交互:数据库连接、SSH远程登录
    • 流媒体中的可靠性优先场景:直播中的关键帧传输
  2. UDP适用场景
    • 实时性要求高的场景:在线视频会议(如Zoom)、多人在线游戏
    • 广播/多播通信:IP电视流媒体、网络时间协议(NTP)
    • 简单查询响应:DNS域名解析、DHCP动态IP分配

3.1 TCP段格式

image-20250523185230444

image-20250523181515506

image-20250523181430367

确认号具有累计确认的特性,如果1-2500B都已经接收,3000-4000B也正确接收,返回的确认号是2500,因为还没收到2500-3000B的内容

image-20250523182747142

image-20250523182916346

紧急指针的序号和上面的序号sqe两者的序号不是一套序号,比如上面的序号是2500-3000B,下面的紧急指针的序号可以是100-199,两者没有关联

image-20250523183424628

一个报文段可能既是SYN段又是ACK段,这三个位并不互斥,不是只能成为其中一个

image-20250523184150778

就是接收方的接收缓冲区目前还可以接收多少字节就要满了,然后发送方就会根据这个数来发送,不会发的太多太快

image-20250523184340737

image-20250523184435246

image-20250523184642276

MSS字段的大小只是数据部分的大小,不包含首部

比如MSS为1000,那么数据部分最大就是1000B

同时,TCP连接的双方通过选项字段可以协商MSS大小,并且双方设置的MSS大小可以不一样

比如A给B的报文段MSS设置为1000,那么A给B发的最大就是1000B

B给A的报文段MSS设置为800,那么B给A发的最大就是800B

3.2 TCP连接管理

传送数据的时候

甲是发送方,乙是接收方

甲发的报文seq=102,ack=556,数据部分有100B

那么乙给甲回复的报文seq=556,ack=202

回复的报文就是 seq就是发过来的ack,而回复报文的ack就是发送报文的seq+数据长度,对直接加就行

image-20250526161516304

三次握手建立连接:

1.SYN=1,seq=x

2.SYN=1,ACK=1,seq=y,ack=x+1

3.ACK=1,seq=x+1,ack=y+1

四次挥手释放连接:

1.FIN=1,seq=u

2.ACK=1,seq=v,ack=u+1

3.FIN=1,ACK=1,seq=w,ack=u+1

4.ACK=1,seq=u+1,ack=w+1

1.三次握手

image-20250526154736672

1.考察SYN,ACK,FIN,seq,ack_seq

image-20250526151935561

image-20250526152649586

客户端发送的序号和服务器发送的序号可以相同也可以不同,比如上图,客户端发送的是以666开始的序号,而服务器是以50开始的序号

服务器握手2的ack是确认的客户端的seq=666,所以是发给客户端的是seq+1,也就是667

而客户端握手3的ack确认的是服务器的seq=50,所以发给服务器的是seq+1,也就是51

即虽然握手1,2不能携带数据,但仍然要消耗一个序号

image-20250526153443516

2.进程TCP状态的转换

image-20250526154313443

3.耗时分析

image-20250526154449694

1RTT是一个来回

从客户端来看,由于握手3就可以直接携带数据,所以用户只需要等握手1过去,握手2回来就是了,是1RTT

而服务器则需要等待握手1,握手2,握手3,一共3趟,也就是1.5RTT,也就是连接建立以后才会开始发送数据

核心:客户端是收到握手2之后才可以发送数据,服务器是收到握手3才可以发送数据

2.四次挥手
1.各个数值

假设客户端是首先发起释放连接的那一方

image-20250526155214017

客户端收到挥手2之后,就不能给服务器发送数据了(因为客户向服务器发送数据的通道已经关闭了,这也是挥手4不能发送数据的原因),而服务器还可以给客户端单向发送数据

挥手1和挥手3实际上可以携带数据,但考试一般默认不携带数据

总结:其实挥手1,2,3都可以携带数据,就是4不行

而挥手2和挥手3之间的序号的差值取决于挥手2和挥手3中间传了多少的数据

2.进程TCP状态的转换

image-20250526160457185

FIN=1的是挥手1和挥手3

3.耗时分析

image-20250526160947074

等待2MSL是为了防止,客户端收到挥手3,然后发给服务器的挥手4丢失了的这种情况。这时候服务器会重新发送一个挥手3,客户端的计时器也会重置 ,然后客户端重新发个挥手4

image-20250526161311224

3.3 可靠传输和流量控制

注:并不是要接收缓冲区满了才可以交付给应用程序,只要接收缓冲区里面的数据是有序的就可以

TCP滑动窗口协议中,发送方滑动窗口的大小规定了发送方最多能够发送的分组数量,只有窗口滑动了,才能往后继续发。分组重传的最大值也是发送方能发送数组的最大值,因而分组重传的数量最多也不能超过滑动窗口的大小

image-20250526213128033

TCP为每个连接设有一个持续计时器,只要发送方收到对方的零窗口通知,就启动持续计时器。

若计时器超时,就发送一个零窗口探测报文,而对方就在确认这个探测报文段时给出现在的窗口值,如果窗口仍然为0,则发送方收到确认报文段后就重新设置持续计时器

image-20250527102952912

连续收到两个长度为MSS的报文段立即返回ack段是因为 这两个段长度很大,重传代价太高了

1.确认号、发送窗口接收窗口

image-20250526201423840

image-20250526201543157

实际中接收窗口大小rwnd一般为8KB,就是以KB为单位的,但是在这例子中,就是8B,是为了简化理解

image-20250526201739192

其实接收和发送缓冲区其实就是char[]数组而已,10B就是长度为10的char型数组

发送窗口大小必须小于接收缓冲区大小,在本例子中,10B的发送缓冲区只有8B能用做发送窗口

而对于服务器来说,8B的发送缓冲区可以全都用作发送窗口,只要满足比接收缓冲区小就可以,显然8B小于10B,是满足的

重点:发送窗口大小不能大于发送缓冲区大小,也不能大于接收方的接收缓冲区的大小

实际上,王道这里讲的是socket编程,发送数据和接收数据也确实是用send和recv进行发送和接收的

image-20250526203322079

一个端口可以建立多个TCP连接,只要对应的socket对象不同就行了。每个TCP连接仅支持一对一通信(全双工)


注:同一端口可以承载多个TCP连接的关键在于四元组的唯一性,而不同的socket对象本质上是对不同四元组的抽象实现

  1. 四元组的唯一性
    TCP连接的标识是四元组(服务端IP、服务端端口、客户端IP、客户端端口)。只要四元组中任意一个元素不同,操作系统内核就会认为这是两个独立的连接。因此,服务端的一个端口可以与多个客户端的不同端口/IP组合建立连接,每个连接对应一个唯一的socket对象
  2. socket对象的本质
    Socket对象是操作系统内核中TCP连接状态的抽象。服务端的主监听socket(listen_socket)仅负责接收新连接请求,而通过accept()函数生成的每个新socket(client_socket)对应一个已建立的连接,其内核状态中包含了完整的四元组信息

误区1:端口只能单连接:错误。端口是逻辑概念,内核通过四元组区分连接,而非单纯依赖端口

误区2:客户端端口不可重用:客户端可通过设置SO_REUSEADDR选项重用本地端口连接不同服务端


TCP协议的发送缓冲区,接收缓冲区在建立连接时由操作系统内核分配,大小不固定

发送窗口和接收窗口大小也并不一定要相等,具体大小由操作系统决定

image-20250526203437854

image-20250526203500699

具体发送过程:

image-20250526204738990

发送缓冲区是0,1,2,3,4,5,6,7,8,9,一开始发送窗口是8,然后把0,1,2发送过去了,接收方返回ack=603,表示第600,601,602个字节已经收到了。之后发送缓冲区就把ack之前的数据全都给清理出去了

image-20250526204942396

接下来就是接收方的接收缓冲区只有5字节了,那么发送窗口的大小也必须调整为5,也就是发送窗口大小。到这里就可以体会到最新确认号,最新接收窗口大小了

image-20250526201543157

image-20250526205138014

2.累积确认

发送两个报文段,一个带着3,4一个带着5,6,不管谁先到达,TCP都有办法确认这四个数据应该在的位置,并且返回较大的确认号,也就是返回607,然后会构造一个不含任何数据的ACK段,告诉接收方607这个序号和接收窗口变成1

image-20250526205346657

接下来就是发送方就发只含1B数据的报文段,因为发送窗口只有1这么大,然后接收缓冲区就满了,满了以后要尽快按序交付给应用程序。交付后接收缓冲区又空了,接收窗口大小又变成了8B,返回ack和接收窗口大小,然后继续传后面的数据

3.捎带确认

image-20250526210007475

就是当服务器接收数据之后,要构造不带数据的ack段进行确认,还有接收窗口大小。此时正好服务器也有数据准备好了,就在发送缓冲区中,那么数据就直接放到ack段中捎带着发回给接收方了

image-20250526210332071

在这个例子中是200,201,202,203,204捎带在ack段中了

这个ack段的首部字段中:

seq=200,ack=610,rwnd=6

接收方客户端就把数据拿下来,然后把发送窗口大小调整为6

image-20250526210824471

那么客户端作为接收方收到数据之后,也得给服务器返回ack段进行确认和接收窗口大小进行调整。而如果此时发送方的发送缓冲区还有东西要发,那么也给捎带发到了服务器了就,就是图中的10,11,12,13,14,15

这个ack段的首部字段中:

seq=610,ack=205,rwnd=5

然后服务器把已经确认的数据弹出缓冲区,并且把发送窗口调整为5

注:并不是要接收缓冲区满了才可以交付给应用程序,只要接收缓冲区里面的数据是有序的就可以

image-20250526211612481

如图所示,虽然接收缓冲区没满,但是16,17有序,那么也可以把这两个交付给应用层

什么是有序?

比如下图中,乱序到达了20,21,22,这时候不可以把这个数据交付给应用程序,因为18和19还没到,不可以称之为有序

image-20250526211710530

4.超时重传

只要发送方没有在规定时间内收到服务器的ack确认段,那么时间到了以后就会进行重传,并重置定时器,直到收到了确认段

1.发送方的发送报文丢失了

定时器到时间后就会重新传

image-20250526212035311

2.接收方发回来的ack段丢了

也是由发送方时间到了以后重新发送,接收方收到了重复的数据,会再次返回ack确认段

image-20250526212447169

5.快重传、立即确认

推迟确认的好处:如果两个段到来的时间间隔很短的话,就可以二合一只返回一个ack段,也就是可以累计确认

立即确认:收到一个报文段立即返回ack确认段

1.推迟确认的缺点

推迟确认并不一定都是好的,下面这个例子体现了推迟确认的缺点

其实就是如果发的这些报文段里面有一个丢了,由于推迟确认机制,在这之后的报文段全都得重新发送

image-20250526213400607

image-20250526213443316

在这个例子中,第2次传的数据丢失了,如下图所示,接收缓冲区大小为4了,构造四个段

分别装着22,23,24,25,直接把四个都发送,接收方收到第一个的时候选择推迟确认0.5秒

image-20250526213749869

image-20250526213906565

其中23丢了,剩下3个都到达了。这是接收缓冲区大小还剩下3而不是1。接收缓冲区大小和确认号是一起看的,从确认号623开始的后面的这部分全是接收缓冲区,所以是3而不是1

所以返回的ack段的ack是623,接收窗口的值是3

image-20250526214206373

image-20250526214243321

发送方收到ack段,把发送窗口调整为3,。但是呢,发送方已经把23,24,25全都发了,所以现在不会再次发送23,24,25这三个数据了,而是会在这里等着他们的ack确认段发过来。但是我们知道这不会发过来,因为接收方就没收到23,不能确认23,由于累计确认,那也就没办法确认24,25。只能等23这个报文段超时,超时后会重传(23报文段超时后不久,24,25也都会超时,并且也会重传)

但其实接收方已经收到24,25报文段了,我们实际上没必要重新传。可是推迟重传导致在发送方看来接收方没收到24,25,所以24,25还会重新传一遍

2.快重传、立即确认

其实就是服务器只要收到一个段,就确认一个段

image-20250526214903439

在这个例子中,第二个23丢失了。但是22到了,会返回ack=623。

24到了,会返回ack=623。25到了,会返回ack=623。

这样就有了3个确认号相同的冗余的ack,此时会立即重传ack对应的报文即623

3.易错点

第一个ack=623不是冗余ack,因为人家本来就该发

后面的624,625发过来的ack=623才是两个冗余ack

那还得有个比如626再发一个ack=623,才是三个冗余ack,才会触发重传机制

image-20250526215649134

3.4 拥塞控制

TCP规定阈值不能小于2

拥塞窗口是发送端根据网络拥塞情况确定的窗口值,而不是接收端确定的。

image-20250527105218716

image-20250527105358332

image-20250527104821947

1.慢开始、拥塞避免

image-20250527105241952

横轴的单位是 RTT,比如2那就是2RTT

竖轴的单位是MSS,比如16就是 16MSS

下图有一个条件是接收窗口无限大,那么发送窗口就取决于拥塞窗口的大小了

image-20250527105840742

一开始是指数级别增长,是2的指数,直到达到阈值ssthresh=16

image-20250527110144827

达到阈值后,变成一次只加1

image-20250527110354964

一直加1加到拥塞窗口大小为24的时候发生了超时重传,说明严重拥塞,这时候重新慢开始,直接把cwnd设为1,重新开始指数增加,只是这次也会把阈值从16调整为 超时重传是拥塞窗口的一半大小即24/2=12这么大。

image-20250527110628138

然后就是一样的过程,慢开始。1+1=2,2+2=4,4+4=8,到了这时 8+8=16>12,所以12这个阈值会限制这次的窗口调整,仅会调整为 8+4=12这么大,然后开始拥塞避免算法慢慢加1

2.快重传、快恢复

image-20250527111640094

在t=12RTT之前都和慢开始那边一样的,而在t=12RTT的时候发生的不是超时重传而是快重传了,即在这个时刻收到了3个重复确认,执行快重传,说明的是网络有点拥塞而不是严重拥塞

和前面的区别就是,前面会直接把拥塞窗口值调整为1MSS,而这个只是调整为发生拥塞时的值的二分之一,称为快恢复

后面就是继续使用拥塞避免算法

image-20250527112218350

注:TCP规定阈值不能小于2

http://www.xdnf.cn/news/672877.html

相关文章:

  • AI in Game,大模型能力与实时音视频技术融合,交出AI应用新答卷
  • EMQX启用单向认证的SSl/TLS连接的配置步骤
  • 如何在加密数据上实现模糊查询?技术方案全解析
  • 视觉语言多模态模型的优化
  • 调试(gdb/cgdb)
  • Python+AI Agent:解锁MCP Servers的智能潜力
  • Python学习(2) ----- Python的类型
  • 《软件工程》实战— 在线教育平台开发
  • Matlab中gcb、gcbh、gcs的区别
  • 下一代 SaaS 平台的 AI 架构重构路径——多租户 AI 服务调度 · 多角色智能辅助 · 嵌入式 AIGC 能力的融合设计
  • 学习黑客 Metasploit 主要组件之 Exploit
  • 实时同步缓存,与阶段性同步缓存——补充理解《补充》
  • 塔能科技:有哪些国内工业节能标杆案例?
  • L1-112 现代战争 - java
  • 将 ubutun 的网络模式 从NAT 改到 桥接模式后,无法上网,linux 没有IP地址 的解决方案
  • Java设计模式之代理模式详解
  • 威联通QNAP替换docker源
  • 被忽视的 App 安全入口:资源文件暴露问题与 iOS 混淆实战(含 Ipa Guard 应用经验)
  • React从基础入门到高级实战:React 核心技术 - 错误处理与错误边界:构建稳定的应用
  • Springboot引入Spring Cloud for AWS的配置中心(Parameter Store和Secrets)
  • RK3568DAYU开发板-平台驱动开发:ADC驱动
  • 火柴INIBOX专业矿机登场,碾压现有Initverse挖矿设备
  • Java构建Tree并实现节点名称模糊查询
  • C 语言学习笔记(结构体1)
  • STM32的DMA入门指南:让单片机学会“自动搬运“数据
  • 【Day38】
  • C语言_文件操作
  • 【深度学习-Day 18】从SGD到Adam:深度学习优化器进阶指南与实战选择
  • 【JavaSE】枚举和注解学习笔记
  • 高考加油(Python+HTML)