提交 fb0e76b2 编写于 作者: 2 2293736867

Computer network chapter5

上级 f1b0c4cd
# Table of Contents
* [1 运输层概述](#1-运输层概述)
* [2 端口](#2-端口)
* [3 常用协议和端口号](#3-常用协议和端口号)
* [4 `TCP`详解](#4-tcp详解)
* [4.1 定义](#41-定义)
* [4.2 报文首部格式](#42-报文首部格式)
* [4.2.1 端口](#421-端口)
* [4.2.2 序号和确认号](#422-序号和确认号)
* [4.2.3 数据偏移](#423-数据偏移)
* [4.2.4 窗口](#424-窗口)
* [4.2.5 五个标志位](#425-五个标志位)
* [4.2.6 选项部分](#426-选项部分)
* [4.3 流量控制](#43-流量控制)
* [4.4 拥塞控制](#44-拥塞控制)
* [4.4.1 简介](#441-简介)
* [4.4.2 `TCP`拥塞控制方法](#442-tcp拥塞控制方法)
* [4.4.3 慢开始和拥塞避免](#443-慢开始和拥塞避免)
* [4.4.4 快重传和快恢复](#444-快重传和快恢复)
* [4.5 超时重传的时间](#45-超时重传的时间)
* [4.5.1 两个基本概念](#451-两个基本概念)
* [4.5.2 基本问题](#452-基本问题)
* [4.5.3 `RTTs`](#453-rtts)
* [4.5.4 `RTT`的计算](#454-rtt的计算)
* [4.6 `TCP`连接](#46-tcp连接)
* [4.6.1 三次握手](#461-三次握手)
* [4.6.2 两次握手?](#462-两次握手)
* [4.6.3 四次挥手](#463-四次挥手)
* [4.6.4 为什么需要`2MSL`](#464-为什么需要2msl)
* [4.6.5 保活计时器](#465-保活计时器)
* [5 `UDP`详解](#5-udp详解)
* [5.1 定义](#51-定义)
* [5.2 首部格式](#52-首部格式)
* [6 `UDP`和`TCP`的对比](#6-udp和tcp的对比)
# 1 运输层概述
物理层、数据链路层、网络层共同解决了主机间通过异构网络互联起来所面临的问题,实现了主机到主机的通信,但实际上通信的真正实体是位于通信两端主机中的两个进程,如何为不同主机上的应用进程提供直接的通信服务是运输层的任务,运输层协议又叫端到端协议。
网络层的作用范围就是主机到主机,运输层的作用范围就是应用进程到应用进程,也叫端到端。
# 2 端口
为了使不同操作系统的计算机的应用程序之间能够进行网络通信,就必须使用统一的方法对`TCP/IP`体系的应用进程进行标识,`TCP/IP`体系的运输层使用端口号来区分应用层的不同应用进程,端口号用`16比特`表示,范围为`0-65535`
端口号只具有本地意义,只是标识计算机应用层中的各个进程,不同计算机中相同的端口号没有联系。
# 3 常用协议和端口号
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210527152848260.png)
# 4 `TCP`详解
## 4.1 定义
`TCP`就是`Transmission Control Protocol`,传输控制协议,面向连接,面向字节流,端到端,可靠的全双工通信协议。
## 4.2 报文首部格式
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210529113029995.png)
- 固定首部`20字节`
- 扩展首部最大`40字节`
### 4.2.1 端口
- 源端口:用于标识发送该`TCP`报文段的应用进程
- 目的端口:用于标识接收该`TCP`报文段的应用进程
### 4.2.2 序号和确认号
序号占32比特,取值范围`[0,2^31-1]`,超过最大值后又重新从0开始,指出该`TCP`报文段数据载荷的第一个字节的序号:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210529113324318.png)
比如上图中的数据载荷中的数据起始第一个字节的序号是166,那么`TCP`报文中的首部的序号就是166。
而确认号也占32比特,范围也是`[0,2^31-1]`,超过最大值后从0重新开始,指出下一个期望收到的报文段中的数据载荷部分第一个字节的序列号,同时也是对之前收到的数据进行确认,简单来说,如果确认号为`n`,那么表示:
- 序列号`n-1`的所有数据已经被正确接收
- 期望接收序列号为`n`的数据
### 4.2.3 数据偏移
`4比特`,以`4字节`为单位,用来指出`TCP`报文段的数据载荷部分的起始处距离`TCP`报文段的起始处有多远,实际上就是首部的长度:
- 首部固定长度`20字节`,因此取值最小为`0101``4字节`为单位)
- 首部最大为`60字节`,因此取值最大为`1111`
### 4.2.4 窗口
窗口占`16比特`,以字节为单位,指出发送本报文段一方的接收窗口,使得接收方根据自己的接收能力去控制发送方的发送能力,也就是流量控制。需要注意的是发送窗口的大小还取决于拥塞窗口的大小,具体来说发送窗口的值就是拥塞窗口和接收窗口中,两者较小的那一个。
### 4.2.5 五个标志位
- `URG`:与紧急指针字段一起使用,`URG=1`时紧急指针字段有效。当发送紧急数据的时候,可以将紧急数据插队列到发送缓存的最前面,并立即封装到一个`TCP`报文段进行发送,紧急指针指出本报文段数据载荷包含了多长的紧急数据
- `ACK`:确认标志位,建立连接后所有的`TCP`报文都必须把`ACK`设置为1
- `PSH`:推送标志位,接收方收到该报文后会尽快上交应用进程,而不需要把缓存填满再向上交付
- `RST`:复位标志位,`RST=1`时表示`TCP`连接出现异常,必须释放连接,然后重新建立连接
- `SYN`:同步标志位
- `FIN`:终止标志位
### 4.2.6 选项部分
包含:
- 最大报文长度`MSS`选项:数据载荷部分最大长度
- 窗口扩大选项:为了扩大窗口
- 时间戳选项:用来计算往返时间`RTT`
- 选择确认选项
## 4.3 流量控制
流量控制就是控制发送方的发送速率,让其适配接收方,简单地说就是接收方让发送方减缓发送的速率,因为接收方来不及接收。核心是利用滑动窗口机制。
在建立连接的时候,接收方会给出接收窗口的值,这个值就是发送方滑动窗口的值,比如下图中A、B建立连接的时候,B告诉A接收窗口的大小为400,那么A的滑动窗口大小就是400:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210527155914557.png)
这样A就可以向B发送400字节的数据,假设A发送300字节的数据,其中最后100字节的数据丢失了:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210527160014737.png)
B收到了前200个字节的数据,并回送`ACK`报文,且`ack=201`,向A表示前200个字节的数据已经收到,同时把窗口大小改为300:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210527160052808.png)
A收到`ACK`后滑动窗口向前移动,移动到第201个字节起始的地方,同时将滑动窗口的值改为300,并将1-200字节的数据从缓存删除。滑动窗口移动后A再发送301-500字节的数据:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210527160331851.png)
发送完301-500字节数据后,由于201-300字节的数据没有收到`ACK`确认,因此会触发超时重传机制。
B收到后,回送`ack=501`,并且再次进行流量控制,将窗口值减少为100:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210527160427430.png)
最后发送501-600字节的数据后,B再次修改窗口的值,改为0,此时A就不能再发送数据了:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210527160543245.png)
A当收到零窗口通知的时候,会触发计时器,计时器超时就会发送零窗口探测报文,仅携带一字节的数据,而B收到零窗口探测报文的时候,会给出自己现在的接收窗口值,如果A收到窗口还是0,会继续触发计时器直到超时再次发送零窗口探测报文,否则将滑动窗口修改为对应的窗口值。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210527161016641.png)
## 4.4 拥塞控制
### 4.4.1 简介
对网络的某一资源的需求超过了该资源所能提供的可用部分,网络性能就要变坏,这种情况就叫拥塞,若出现拥塞而不控制,整个网络的传输量将随着输入负荷的增大而下降,如下图所示,吞吐量在一定范围内随着输入负载的增大而增大,但当增大到一定程度的时候,吞吐量就不再增长:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210528155955892.png)
但实际情况中,如果不进行拥塞控制,则会陷入死锁状态:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210528160939322.png)
而实际的拥塞控制曲线应该接近于理想曲线:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210528160958868.png)
### 4.4.2 `TCP`拥塞控制方法
`TCP`拥塞控制有四种方法:
- 慢开始(`slow-start`
- 拥塞避免(`congestion avoidance`
- 快重传(`fast retransmit`
- 快恢复(`fast recovery`
`TCP`发送方会维护一个叫做拥塞窗口`cwnd`的变量,大小取决于网络拥塞程度,当没有出现拥塞时就将拥塞窗口增大,否则减少(也就是出现拥塞,发生了超时重传)。一开始将拥塞窗口的值与发送窗口的值相等,同时需要维护一个叫`ssthresh`的状态变量:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210528162803123.png)
### 4.4.3 慢开始和拥塞避免
慢开始就是把拥塞窗口的值每次都增大,具体规则是当收到前面报文的确认时候,把拥塞窗口的值变为原来的两倍。而拥塞避免就是当使用慢开始算法达到阈值(`ssthresh`)时使用的缓慢增大拥塞窗口的算法,具体规则是当收到前面报文的确认的时候,把拥塞窗口的值加1,如图所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210528163854109.png)
而当出现了重传的时候,会将`ssthresh`的值修改为当前出现重传时拥塞窗口的一半,并将拥塞窗口的值改为1,再次使用慢开始算法:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210528164021956.png)
### 4.4.4 快重传和快恢复
快重传就是发送方快速重传已经丢失的分组,而不用等待某个分组的超时重传计时器超时,这样需要要求接收方收到报文后需要立即发送确认,而发送方一旦收到连续的三个重复确认,就将相应的报文进行重传,而无需等待计时器超时:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210528164815603.png)
比如上图中的连续发送三个重复的`M2`确认,这样发送方就知道`M3`丢失,立即重传`M3`
而快恢复就是当收到连续的三个重复确认的时候,不是启动慢开始算法,而是将慢开始的门限`ssthresh`的值和拥塞窗口的值改为当前窗口值的一半,开始执行拥塞避免算法。
## 4.5 超时重传的时间
### 4.5.1 两个基本概念
- `RTT`:往返时间
- `RTO`:超时重传时间
### 4.5.2 基本问题
`RTO`小于`RTT`的时候,如图所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210528165735793.png)
过短的`RTO`会引起多次的重传,而如果`RTO`过大:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210528165759211.png)
会导致空闲时间增大,传输效率下降。
因此,合理的`RTO`值是略大于`RTT`的:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210528165937934.png)
### 4.5.3 `RTTs`
由于网络中的环境的动态变化的,因此,如果将`RTO`的值固定,可能会引起不必要的重传,或者造成过多的网络空闲,因此,`RTO`的值需要动态进行计算。
这样就引申出了`RTTs``RTTs`是利用每次测量得出的`RTT`样本计算的加权平均`RTT`值,又叫平滑的往返时间,计算公式如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210528170328983.png)
`RTO`的值,就需要略大于`RTTs`。具体来说,标准建议如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210528170522557.png)
### 4.5.4 `RTT`的计算
正常情况下`RTT`计算不难,但是如果出现了超时:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210528170819169.png)
- 若发送报文超时,且源主机误将对重传报文的确认当做对原报文的确认,则会使得计算的`RTT`偏大,降低传输效率
- 若确认报文超时,且源主机误将对原报文的确认当做对重传报文的确认,会使得计算的`RTT`偏小,触发不必要重传
因此,计算超时报文`RTO`的方法是报文每重传一次,就将`RTO`增大一些,典型的做法是增大到原来的2倍。
## 4.6 `TCP`连接
`TCP`是面向连接的协议,基于运输连接来传送`TCP`报文段,`TCP`连接的建立是每一次`TCP`连接中不可缺少的部分,有以下三个阶段:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210529095701556.png)
### 4.6.1 三次握手
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210529100548898.png)
流程:
- 服务器需要先进入“被动打开状态”,也就是服务器需要先进入监听状态
- 客户端进入主动打开状态,完成一些初始工作(创建传输控制块,服务器也需要)
- 客户端发起第一次握手:发送同步位`SYN=1`以及带有一个序列号`seq=x`(随机生成)的报文,客户端进入`SYN-SENT`状态,注意由于`TCP`规定`SYN=1`的报文不能携带数据,因此该报文不能携带数据
- 服务器发起第二次握手:监听进程收到报文后,会针对客户端的报文进行确认,具体来说,回送同步位`SYN=1`以及确认位`ACK=1`的报文,同时设置序列号`seq=y`(随机生成)以及确认号`ack=x+1`(客户端的报文序列号+1),服务器进入`SYN-RCVD`状态,注意由于该报文同步位为1(`SYN=1`),因此也不能携带数据
- 客户端发起第三次握手:收到服务器应答后,回送确认位`ACK=1`,序列号`seq=x+1`(上一次发送的序列号+1)以及确认号`ack=y+1`(服务器的报文序列号+1)的报文。`TCP`规定普通的确认报文是可以携带数据的,因此该报文可以携带数据
### 4.6.2 两次握手?
为什么不能两次握手?
因为两次握手不能防止已失效的请求报文创建多余错误的连接,这样就会浪费服务器资源,图示如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210529101330286.png)
- 一开始第一个`TCP`连接请求报文发生了延迟
- 于是触发了超时重传,第二个`TCP`连接请求报文被发送
- 第二个`TCP`连接报文正常速度到达服务器,服务器回送确认后进入连接已建立状态
- 客户端收到服务器的报文后进入连接已建立状态
- 双方发送数据后正常挥手关闭连接
- 但关闭后,之前的第一个`TCP`连接请求报文到达了服务器,服务器误认为这是正常的`TCP`连接请求报文(而实际上是过期的,是延迟到达的,这个连接已经断开了),这样服务器回送确认后进入连接已建立状态
- 客户端再次收到服务器的确认报文后,由于客户端并没有再次发起请求,因此对该报文会采取忽略处理
- 这样就导致了服务器中一个空连接的出现,浪费了服务器资源
### 4.6.3 四次挥手
图示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210529102338291.png)
流程:
- 客户端中`TCP`应用进程通知主动关闭`TCP`连接,`TCP`连接由客户端主动发起关闭
- 第一次挥手:客户端发送终止位为1(`FIN=1`)以及确认位为1(`ACK=1`)的报文,同时该报文中序列号`seq=u`(客户端最后发送的一个报文的序列号+1),确认号`ack=v`(客户端最后收到数据的最后一个字节序号+1),客户端进入`FIN-WAIT-1`状态
- 第二次挥手:服务器发送确认位`ACK=1`、序列号`seq=v`(服务器上一次发送的报文的序列号+1)、确认号`ack=u+1`(对客户端发送的序列号`seq=u`的报文的确认),同时服务器通知上层的应用进程准备关闭`TCP`连接,服务器进入`CLOSE-WAIT`状态,客户端收到后进入`FIN-WAIT-2`状态
- 第三次挥手:服务器发送终止位`FIN=1`、确认位`ACK=1`、序列号`seq=w`(发送了若干个剩余报文)、确认号`ack=u+1`(对客户端第一次挥手报文的确认)的报文,服务器进入`LAST-ACK`状态
- 第四次挥手:客户端回送确认位`ACK=1`,序列号`seq=u+1`(第一次挥手报文的序列号+1)、确认号`ack=w+1`(服务器最后一次挥手报文的序列号+1),然后客户端进入`TIME-WAIT`状态,服务器的连接关闭
- 客户端等待`2MSL`后报文关闭,`MSL`是最长报文段寿命
### 4.6.4 为什么需要`2MSL`
有两个原因:
- 防止第四次挥手报文超时导致服务器一直处于`LAST-ACK`状态并不断超时重传`FIN=1`的报文
- 等待`2MSL`后可以确保所有的报文都是新连接产生的,而不是以前连接中的报文
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210529111654452.png)
- 如果第四次挥手报文丢失,如上图所示
- 会导致服务器一直处于`LAST-ACK`状态,超时重传`FIN=1`的连接释放报文
- 但是此时客户端已经处于关闭连接状态,会直接忽略该报文
- 这样会不断触发服务器的超时重传连接释放报文,一直无法进入关闭状态
另一方面,等待`2MSL`后关闭,可以确保本次连接持续时间内所产生的所有报文消失,这样就确保了新的`TCP`连接不会出现旧的连接报文段。
### 4.6.5 保活计时器
`TCP`服务器每收到一次`TCP`客户端进程的数据,就会重新设置并启动保活计时器(2小时定时),若计时器超时,`TCP`服务器就会向`TCP`客户端发送一个探测报文段,以后每隔`75s`发送一次,若10次后仍无法收到响应,则认为`TCP`客户端出现了故障,服务器就关闭了该连接。
# 5 `UDP`详解
## 5.1 定义
`UDP``User Datagram Protocol`,用户数据报协议)是传输层的协议,在`IP`数据报服务之上增加了最基本的服务:
- 复用
- 分用
- 差错检测
`UDP`提供不可靠服务,是无连接的,没有拥塞控制。`UDP`是面向报文的,对于应用层的报文添加首部后直接交付网络层,既不合并,也不拆分。
## 5.2 首部格式
`UDP`数据报分为首部和数据部分,整个`UDP`数据报作为`IP`数据报的数据部分封装在`IP`数据报中,报文结构如下:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20210527162024577.png)
首部共8个字节,4个字段组成,每个字段两字节:
- 端口:不解释
- 长度:`UDP`数据报的总长度,也就是首部+数据的长度
- 检验和:检测`UDP`数据报中是否有错,有错则丢弃
# 6 `UDP`和`TCP`的对比
- `UDP`是无连接的,数据可以直接发送,`TCP`是面向连接的,发送数据之前需要先三次握手,发送完毕后四次挥手
- `UDP`支持多播、单播、广播,也就是支持一对一、一对多、一对全的通信,`TCP`仅支持单播,也就是支持一对一通信
- `UDP`面向应用报文,`TCP`面向字节流,`UDP`不会处理应用层交付的应用报文,直接加上首部然后发送,而`TCP`将应用报文看做字节流,每次发送一定数量的字节,接收方收到后按需交付应用层
- `UDP`向上层提供无连接不可靠的传输服务,适合视频会议等实时应用,而`TCP`向上层提供面向连接的可靠传输服务,适用于要求可靠传输的应用,比如文件传输
- `UDP`首部开销小,仅`8字节`,而`TCP`的首部`20-60字节`
......@@ -4,3 +4,4 @@
- [第二章:物理层](https://github.com/2293736867/CSBookNotes/blob/main/ComputerNetwork/Chapter2/README.md)
- [第三章:数据链路层](https://github.com/2293736867/CSBookNotes/blob/main/ComputerNetwork/Chapter3/README.md)
- [第四章:网络层](https://github.com/2293736867/CSBookNotes/blob/main/ComputerNetwork/Chapter4/README.md)
- [第五章:运输层](https://github.com/2293736867/CSBookNotes/blob/main/ComputerNetwork/Chapter5/README.md)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册