传输层
传输层存在的基本理由:进程到进程的传递。
(网络层不对数据报分组进行排序)
传输层的协议的类型
{
U
D
P
:简单的协议
T
C
P
:复杂的传输层协议
S
C
T
P
:为多媒体这样的多接口与多流应用而设计
传输层的协议的类型\begin{cases}UDP:简单的协议\\TCP:复杂的传输层协议\\SCTP:为多媒体这样的多接口与多流应用而设计\end{cases}
传输层的协议的类型⎩
⎨
⎧UDP:简单的协议TCP:复杂的传输层协议SCTP:为多媒体这样的多接口与多流应用而设计
1. 进程到进程的传递
需求:
- 数据链路层:相邻节点之间的帧传递——节点到节点的传递 node - to - node delivery
- 网络层:两台主机之间的数据包交换——主机到主机的传递 host - to - host delivery
实际的通信发生在两个进程之间,我们需要进程到进程的传递。
但是任何时刻,源主机上运行着多个进程,并在目的主机上也运行着多个进程。需要某种机制,将源主机上的某个进程的数据传输到目的主机上的对应进程上。
![image-20211208153902282](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211208153902282.png)
1.1 客户机/服务器模式 Client/Server Paradigm
实现进程到进程间通信的方式:两个进程以客户client/server的方式进行通信。
客户机client:本地主机上的进程称为client,通常需要来自远程主机上的进程提供的服务。
服务器server:远程的主机称为服务器。
这两个进程(客户机和服务器)有着相同的名字。
e.g. 客户机从远程机器上获取日期和时间,需要在本地主机上运行Daytime客户进程和远程机器上运行Daytime服务进程。
目前OS支持多用户和多程序运行的环境。一个远程计算机在同一时间可以运行多个服务器程序。
我们必须定义:
- 本地主机 local host
- 本地进程 local process
- 远程主机 remote host
- 远程进程 remote process
1.1.1 寻址
需要传送消息到多个目的地之一的某个特定目的地时,需要一个地址。
1.1.1.1 数据链路层的寻址
如果不是点到点连接(点到多点),那么需要一个MAC地址从多个节点中选择一个节点。数据链路层的帧需要:
- 一个目的端MAC地址用于传送数据
- 一个源地址用于下一节点的回答
1.1.1.2 网络层的寻址
网络层,需要一个IP地址来选择百万主机中的一个主机。
- 网络层中的数据报需要一个目的IP地址用来传送数据
- 需要源IP地址用来接收目的主机的回答
1.1.1.3 传输层
端口号 port number:传输层地址,利用这一地址从目的主机上运行的多个进程中选择相应的进程。
- 目的端口号用于传送
- 源端口号用于接收回答
端口号为0~65535之间的16位整数
1.1.2 临时端口号与熟知端口号
客户机的端口号(ephemeral port number):自己定义的,运行在客户机上的传输层软件随机选择,这是临时端口号(ephemeral port number )。
服务器的端口号(well-known port number):这个端口号不能随机选择。如果随机选择,那么访问这个服务器时将不知道端口号。使用全局端口号——熟知端口号(well-known port number)。
当然,有时,一些客户端也被分配了熟知端口号。
![image-20211208162040451](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211208162040451.png)
1.1.3 IANA范围
端口号地址被IANA划分成三种范围:
端口号地址的范围
{
W
e
l
l
−
k
n
o
w
n
p
o
r
t
s
{
范围:
0
−
−
1023
性质:由
I
A
N
A
分配
R
e
g
i
s
t
e
r
e
d
p
o
r
t
s
:
{
范围:
1024
−
−
49152
性质:
I
A
N
A
不分配也不控制,可以在
I
A
N
A
注册防止重复
D
y
n
a
m
i
c
p
o
r
t
s
{
范围:
49152
−
−
65535
性质:不受控制也不需要注册,可以由任何进程使用
端口号地址的范围\begin{cases}Well-known\ \ ports\begin{cases}范围:0--1023\\性质:由IANA分配\end{cases}\\Registered\ \ ports:\begin{cases}范围:1024--49152\\性质:IANA不分配也不控制,可以在IANA注册防止重复\end{cases}\\Dynamic\ \ ports\begin{cases}范围:49152--65535\\性质:不受控制也不需要注册,可以由任何进程使用\end{cases}\end{cases}
端口号地址的范围⎩
⎨
⎧Well−known ports{范围:0−−1023性质:由IANA分配Registered ports:{范围:1024−−49152性质:IANA不分配也不控制,可以在IANA注册防止重复Dynamic ports{范围:49152−−65535性质:不受控制也不需要注册,可以由任何进程使用
1.1.4 套接字地址
进程到进程传递需要两个标识符:IP地址和端口号。
套接字地址Socket Address:IP地址和端口号的结合。
{
客户套接字:唯一定义了客户机进程
服务器套接字:唯一定义了服务器进程
\begin{cases}客户套接字:唯一定义了客户机进程\\服务器套接字:唯一定义了服务器进程\end{cases}
{客户套接字:唯一定义了客户机进程服务器套接字:唯一定义了服务器进程
传输层协议需要一对套接字地址:客户机套接字地址和服务器套接字地址。
IP头部:IP地址
UDP/TCP头部:端口号
1.2 无连接的服务和面向连接的服务
传输层协议可以是无连接的或者是面向连接的服务。
1.2.1 面向无连接的服务
分组从一方发给另一方,不需要建立连接和释放连接。
隐患:分组没有编号。可能延迟,丢失,无序到达。无确认过程。
UDP是无连接的。
1.2.2 面向连接的服务
面向连接的服务中,在发送方和接收方之间建立一个连接,然后传送数据,最后释放连接。
TCP和SCTP是面向连接的。
1.3 可靠服务和不可靠服务
1.3.1 可靠服务和不可靠服务的应用
传输层的服务有可靠的和不可靠的,主要是使用可靠的协议或者是不可靠的协议实现的。
传输层服务
{
可靠服务
{
需求:应用层需要可靠性,那么使用可靠服务
传输层实现流量控制和差错控制
服务较慢或者更复杂
不可靠服务
{
需求:不需要可靠性,使用自己的流量和差错控制
需要快速服务或者本质特性不要求流量和差错控制(如,实时应用)
传输层服务\begin{cases}可靠服务\begin{cases}需求:应用层需要可靠性,那么使用可靠服务\\传输层实现流量控制和差错控制\\服务较慢或者更复杂\end{cases}\\不可靠服务\begin{cases}需求:不需要可靠性,使用自己的流量和差错控制\\需要快速服务或者本质特性不要求流量和差错控制(如,实时应用)\end{cases}\end{cases}
传输层服务⎩
⎨
⎧可靠服务⎩
⎨
⎧需求:应用层需要可靠性,那么使用可靠服务传输层实现流量控制和差错控制服务较慢或者更复杂不可靠服务{需求:不需要可靠性,使用自己的流量和差错控制需要快速服务或者本质特性不要求流量和差错控制(如,实时应用)
1.3.2 协议的可靠性
UDP:不可靠协议
TCP和SCTP:可靠协议
1.3.3 传输层提供可靠性的必要性
原因:
- 数据链路层的可靠性只存在于两个节点之间,而我们需要端到端的可靠性。
- 网络层是不可靠的(尽力传递),必须在传输层实现可靠性。
TCP使用滑动窗口协议实现差错控制和流量控制。
1.3.4 三种协议
三种协议在TCP/IP协议簇中的位置。
![image-20211208172442293](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211208172442293.png)
TCP和UDP的应用场景:
- TCP应用场景
(1)客户端和服务器需要多次交互才能实现特定功能。如接收邮件和发送邮件。
(2)接收的邮件需要分段传输。如浏览器访问网页时,网页中的图片和HTML文件需要分段后发送给浏览器,QQ传送文件时也需要分段,此时使用TCP协议
- UDP应用场景
(1)客户端程序和服务器端程序通信,应用程序发送的数据包不需要分段。如域名解析时的请求报文和返回的解析结果。
(2)实时通信。
(3)多播或者广播。
2. UDP(User Datagram Protocol)
用户数据报协议(UDP):无连接不可靠传输层协议。
UDP提供服务:
- 提供进程到进程通信而不是主机到主机通信,没有给IP服务增加任何东西。
- 提供非常有限的差错检验。
UDP优点:
- 开销最小。如果一个进程要发送很短的报文,且不在意可靠性,那么可以使用UDP。
2.1 熟知端口号
UDP使用的熟知端口号:
![image-20211208174057562](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211208174057562.png)
2.2 用户数据报
UDP分组称为用户数据报 User datagram:8字节固定头部
用户数据报的字段:
![image-20211208174741955](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211208174741955.png)
-
源端口号
在源主机上运行的进程使用的端口号:16位。端口号范围为0-65535。
对于客户端:大多是情况下是临时端口号
服务器:大多数情况下是熟知端口号
-
目的端口号
和源端口号类似
-
总长度
16位字段,定义了用户数据报的总长度,头部加上数据。
总长度是65536.但是UDP数据报必须比这个小,UDP数据报存放在具有总长度为65536字节的IP数据报中。
实际上这个字段是没有必要的。IP数据报中有定义总长度字段。
UDP长度 = IP长度 - IP头部长度
2.3 校验和
UDP分组的校验和和IP以及ICMP校验和的计算不一样。UDP校验和包括三个部分:
U
D
P
校验和
{
伪头部
U
D
P
头部
从应用层来的数据
UDP校验和\begin{cases}伪头部\\UDP头部\\从应用层来的数据\end{cases}
UDP校验和⎩
⎨
⎧伪头部UDP头部从应用层来的数据
2.3.1 伪头部
IP分组头部的一部分,其中某些字段要填入0,用户数据报封装在IP分组中。
![image-20211215152801880](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211215152801880.png)
- 伪头部在IP数据报头部破坏时,确保不会被提交到错误的主机
- 协议字段可确保这个分组属于UDP,而不属于其他的传输层协议。如果在传输过程中这个值改变了,在接收端计算校验和时可以检验出来,UDP可以丢弃这个分组,不会传递给错误的协议
![image-20211208191825183](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211208191825183.png)
2.3.2 可选校验和
校验和的计算以及在用户数据报中包括的校验和都是可选的,如果不进行校验和的计算,那么这些字段就填入全1。
注意:校验和时全1是不可能的(想象一下,只有数据全是0时才会出现校验和是全1的情况,而这是不可能的)
2.4 UDP操作
2.4.1 无连接的服务 connectionless service
无连接服务:UDP发送出去的每一个用户数据报都是独立的数据报,每个数据报之间没有关系。
用户数据报不进行编号。
不进行连接的建立和连接中止——每一个用户的数据报可以沿着不同的路径传递。
2.4.2 流量控制和差错控制
-
流量控制
UDP没有流量控制,没有窗口机制,如果到达的报文太多,接收方可能会溢出。
-
差错控制
UDP没有差错控制,假如接收方使用校验和检测出差错时,就丢弃
由于缺少流量控制和差错控制,使用UDP的进程必须要提供这些机制。
2.4.3 封装和拆封
从一个进程发送到另一个进程,UDP协议就要将报文在IP数据报中进行封装和拆封。
2.4.3.1 排队Queuing
端口的实现:队列与端口的实现是联系在一起的。
客户机端,进程启动时从OS请求一个端口号。
请求的端口号
{
有些实现创建一个入队列和一个出队列,与每一个进程相关联
有些只创建与每一个进程相关联的入队列
请求的端口号\begin{cases}有些实现创建一个入队列和一个出队列,与每一个进程相关联\\有些只创建与每一个进程相关联的入队列\end{cases}
请求的端口号{有些实现创建一个入队列和一个出队列,与每一个进程相关联有些只创建与每一个进程相关联的入队列
note:如果一个进程想与多个进程通信,那么也只得到一个端口号,而最后也只有一个出队列outgoing queue和入队列 incoming queue。进程撤销时,队列撤销。
排队过程:
a.客户机的队列创建
客户机进程使用在请求中指明的源端口号将报文发送到出队列。UDP逐个将报文取出,加上UDP头部交给IP。
出队列可能会发生溢出,操作系统要求客户进程在继续发送报文之前要等待。
当报文到达客户端时,UDP检查一下确认用户数据报中的目的端口号字段指明的端口号有创建入队列。
- 如果有:UDP将接收到的用户数据报放在该队列的末尾
- 如果没有:UDP丢弃该数据报,请求ICMP发送目的端不可达报文
入队列可能会溢出,溢出时向服务器发送端口不可达报文。
b.服务器的队列创建
最简单的形式:服务器在开始运行的时候就用熟知端口请求入队列和出队列。只要服务器运行,那么队列就一直是打开的。
![image-20211208201151236](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211208201151236.png)
2.4.4 UDP的使用
UDP适用的应用如下:
- 需要简单的请求-响应通信,较少考虑流量控制和差错控制
- 适用于内部有流量控制和差错控制的进程
- 多播
- 可用来管理进程,如SNMP
- 可用于路由选择更新协议,如RIP
3. TCP
传输控制协议Transmission Control Protocol:
- 面向连接的协议。为发送数据在两个TCP之间建立一个虚拟连接。
- TCP在传输层适用差错控制和流量控制
- TCP是可靠的协议,为IP服务增加了面向连接和可靠性的特性
3.1 TCP服务
3.1.1 进程到进程的通信
TCP’s well known ports
![image-20211208202023003](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211208202023003.png)
3.1.2 流传递服务
3.1.2.1 字节流形式的传递
TCP是面向流的协议。TCP允许发送进程以字节流 stream of bytes的形式传送数据。
TCP建立一种环境,两个进程好像是由一个假象的“管道”进行连接,管道通过因特网传输进程的数据。发送进程产生(写入)字节流,接收进程消费(读出)这些字节流。
3.1.2.2 发送和接收缓冲区
由于发送和接收进程可能以不同的速度写入和读出数据,所以TCP需要用于存储的缓冲区。
-
每个方向都有一个缓冲区
缓冲区 { 发送缓冲区 { 空存储单元,可由发送进程填充 已经发送但未确认 将要发送的字节 接收缓冲区 { 空存储单元 接收到的存储单元,可以由接收进程读出 缓冲区\begin{cases}发送缓冲区\begin{cases}空存储单元,可由发送进程填充\\已经发送但未确认\\将要发送的字节\end{cases}\\接收缓冲区\begin{cases}空存储单元\\接收到的存储单元,可以由接收进程读出\end{cases}\end{cases} 缓冲区⎩ ⎨ ⎧发送缓冲区⎩ ⎨ ⎧空存储单元,可由发送进程填充已经发送但未确认将要发送的字节接收缓冲区{空存储单元接收到的存储单元,可以由接收进程读出 -
缓冲区用于实现TCP的流量控制和差错控制
-
实现缓冲的一种方法:使用循环数组;
-
缓冲区通常是上百或者上千个字节,取决于实现方法。
-
实际上缓冲区的大小也不一定是一样的。
![image-20211208203932646](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211208203932646.png)
3.1.2.3 段
IP层作为TCP服务的提供者,需要以分组的形式而不是以字节流的形式发送数据。
段:传输层中,TCP将多个字节分组合在一起成为一个分组。这个分组称为段。
TCP给每个段添加头部(控制目的),然后将该段传递给IP层。段被封装到IP数据报中,然后再进行传输。
这些段可能被无序接收,丢失,损坏和重发。均由TCP处理。
一切对接收进程透明。
![image-20211208205542417](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211208205542417.png)
3.1.3 全双工服务
数据可以在同一时间双向流动。每一方TCP都有发送和接收缓冲区,他们能在双向发送和接收段。
3.1.4 面向连接的服务
TCP是面向连接的协议。站点A的一个进程要发送和接收来自站点B的数据时,步骤如下:
- 在两个TCP之间建立一个连接——虚连接
- 在两个方向交换数据
- 连接中止
3.1.5 可靠的服务
TCP使用确认机制acknowledgment mechanism来检查数据是否安全和完整到达。
3.2 TCP特点
3.2.1 序号系统
TCP的段没有段特有的段序号,TCP在段头采用序号(sequence number)和确认号(acknowledgement number)
字节序号byte number:TCP为每一个字节进行编号。
byte number的特点:
- 每个方向上的序号都是独立的。
- 存储在缓冲区时进行编号
- 在 0 ∼ 2 32 − 1 0\sim 2^{32}-1 0∼232−1之间生成一个随机数作为第一个字节的序号(不一定是从0开始编号的)
(1)序号 Sequence Number
TCP对发送的每一个段分配一个序号,每个段的序号是这个段中的第一个字节的序号。
当一个段携带数据和控制信息时,使用一个序号;如果一个段没有携带用户数据,那么逻辑上不定义序号。虽然字段存在,但是是毫无意义的。
(2)确认号 acknowledgment number
TCP通信是全双工的,每一方使用确认号来确认已经收到的字节。
确认号定义了该方预期接收的下一个字节的序号。确认号是累积的(累计确认):确认号 = 收到的最后一个字节 + 1 = 预期接收的下一个字节。
3.3 TCP段格式
段 { 头部: 20 − − 60 b y t e s { 固定头部: 20 b y t e s 选项 应用层的数据 段\begin{cases}头部:20--60\ bytes\begin{cases}固定头部:20bytes\\选项\end{cases}\\ 应用层的数据\end{cases} 段⎩ ⎨ ⎧头部:20−−60 bytes{固定头部:20bytes选项应用层的数据
-
源端口地址Source port address:16位字段,定义发送方的端口号
-
目的端口地址Destination port address:16位字段,定义接收方的端口号
-
序列号 Sequence Number:32位字段,是段中的第一个字节的编号。
- 确认号Aknowledge Number:32位字段,定义了期望从发送方接收到的字节号。确认号 = 发送方的字节号 + 1。捎带:确认和数据可以一起发送,称为捎带。
-
头部长度Header Length:4位字段,单位为4字节。头部的长度在20bytes到60bytes之间,因此,min = 0101 = 5,max = 1111 = 60
-
保留 reserved:保留,未使用
-
控制 control:定义了6种不同的控制位或者标记,同一时间可以设置一位或者多位
c o n t r o l { U R G : 紧急指针有效,置 1 时表示数据紧急,将紧急数据放在段的开始 A C K :确认有效 P S H :请求急迫,发送端的 T C P 窗口不必等待窗口被填满,这个段包含的数据必须尽快地发送给解释程序 R S T :连接复位 S Y N :同步序列号 F I N :终止连接 control\begin{cases}URG:紧急指针有效,置1时表示数据紧急,将紧急数据放在段的开始\\ACK:确认有效\\PSH:请求急迫,发送端的TCP窗口不必等待窗口被填满,这个段包含的数据必须尽快地发送给解释程序\\RST:连接复位\\SYN:同步序列号\\FIN:终止连接\end{cases} control⎩ ⎨ ⎧URG:紧急指针有效,置1时表示数据紧急,将紧急数据放在段的开始ACK:确认有效PSH:请求急迫,发送端的TCP窗口不必等待窗口被填满,这个段包含的数据必须尽快地发送给解释程序RST:连接复位SYN:同步序列号FIN:终止连接
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kdOdPkEb-1664536156894)(https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211215153515680.png)]- 窗口大小Window Size:16位字段,对方必须维持的窗口大小,单位为bytes:窗口的最大长度为65536字节。称为接收窗口rwnd,由接收方确定。——流量控制
- 校验和CheckSum:16位字段,TCP与UDP校验和计算过程相同,但是校验和对UDP来说是可选的,但是对TCP来说是强制的。对于TCP的伪头部,协议字段的值是6。
- 紧急指针字段 Urgent Pointer:16位字段,当紧急指针标志位置位时才有效,当段包含了紧急数据时使用。这个数字加上序列号就是紧急数据的最后一个字节。——紧急数据放在段的最开始
- 选项Options:TCP只规定了一种选项,即最大报文长度MSS。MSS是TCP数据报中的数据字段的最大长度。数据字段加上TCP首部才是整个的TCP数据报。
3.4 TCP连接
网络层提供的服务不可靠,给传输层带来了很大的困难:
- 段丢失
- 段失序
传输层需要解决的问题:
- 连接的建立和终止 【虚拟链接,获得相同的服务】
- 有序交付
- 副本检测 【新段or重发段】
- 重传策略
- 故障恢复
- 流量控制
- 拥塞控制
TCP是面向连接的协议:源端和目的端之间建立一条虚路径,属于一个报文的所有段沿着虚路径发送——有利于处理帧的丢失和丢失帧的重发。
IP不知道TCP的重新排序的过程。
面向连接的传输有三个阶段:
- 连接建立
- 数据传输
- 连接中止
连接建立要解决的问题:
-
要使每一方都能确认对方的存在
-
允许双方协商参数
参数 { 最大报文长度 最大窗口大小 服务质量 参数\begin{cases}最大报文长度\\最大窗口大小\\服务质量\end{cases} 参数⎩ ⎨ ⎧最大报文长度最大窗口大小服务质量
- 能够对传输资源进行分配
传输资源 { 缓存大小 连接表中的项目 传输资源\begin{cases}缓存大小\\连接表中的项目\end{cases} 传输资源{缓存大小连接表中的项目
3.4.1 连接建立
TCP:全双工,数据传输双方都需要对通信进行初始化,并得到对方的认可。
3.4.1.1 三次握手 Three- Way Handshaking
(例子背景:客户要与服务器建立连接),过程如下:
-
服务器请求被动打开:服务器告诉TCP,他已经准备好接收一个连接,称为请求被动打开passive open
-
客户机请求主动打开:想要与服务器进行通信的客户机告诉他的TCP,需要连接到特定的服务器,TCP进行三次握手的过程:
(1)客户发送第一个SYN段,这个段仅有SYN被置位,用于序列号同步。
SYN占用一个序列号。当数据开始传输时,序列号加1。(仅有ACK不会+1)
(2)服务器发送第二个段,两个标志位SYN和ACK被置位。表示另一方向通信的SYN段,并且用ACK标志表示对第一个SYN的确认,占用一个序列号
(3)客户机发送第三个段,仅仅是一个ACK段,用ACK标志和确认号序列表示已经收到的段。这个段的序列号与SYN段的序列号相同,ACK段没有占用任何序列号。
Note:
单独的ACK如果不携带数据,则它不占用序列号。
SYN不携带数据,但是占用一个序列号
SYN+ACK不携带数据,但是占用一个序列号
3.4.1.2 同时打开 Simultaneous Open
两个进程都发出主动打开的情况,极少发生。这种情况下,双方同时发出SYN+ACK段,在他们之间建立一条单独的连接。
3.4.1.3 SYN洪泛攻击
SYN洪泛攻击:攻击者将大量的SYN段发送到一个服务器,在数据报中通过伪装IP地址假装这些段来自不同的客户端时就发生了这种情况。
属于拒绝服务供给,使服务器资源耗尽。
TCP某些实现有减轻SYN攻击影响的策略:
{
在短期内对请求的链接进行限制
过滤掉来自不需要的源地址的数据报
使用
c
o
o
k
i
e
推迟资源分配直到一个完整的链接建立
\begin{cases}在短期内对请求的链接进行限制\\过滤掉来自不需要的源地址的数据报\\使用cookie推迟资源分配直到一个完整的链接建立\end{cases}
⎩
⎨
⎧在短期内对请求的链接进行限制过滤掉来自不需要的源地址的数据报使用cookie推迟资源分配直到一个完整的链接建立
3.4.2 数据传输Data transfer
3.4.2.1 传输过程
连接建立后可进行双向数据传输data transfer,客户机和服务器双方都发送数据和确认。
在段内携带确认时,也可以传输数据:数据捎带确认 data piggybacked with the data
![image-20220825122239024](https://cdn.jsdelivr.net/gh/Holmes233666/blogImage@main/img/image-20220825122239024.png)
3.4.2.2 急迫数据
-
非急迫情况
TCP使用缓冲区存储来自发送方应用程序的数据流。发送方TCP可以选择段的大小。接收方在数据到达时也将数据进行缓存。并在应用程序准备就绪或者是接收方TCP认为合适的时候就将这些数据传递给应用程序。灵活性增加了TCP的效率。
-
急迫情况
比如双方的应用进行交互式通信,总是希望接收方能够立即响应,数据的延迟传输和延迟传递是不可接受的。
PUSH置位时就表示这个段包含的数据必须尽快传送给应用程序,不需要等待更多的需求。
TCP可以选择使用或者不使用这个操作。
3.4.2.3 紧急指针
URG位置位,紧急数据放在段的开始。段的其他部分可以包含普通数据。
EXAMPLE:处理数据时异常终止数据Ctrl +C
3.4.3 连接中止 Connection Termination
交换数据的任一方均可关闭连接,通常由客户端发起。关闭连接的方法有两种:
{
三次握手
T
h
r
e
e
−
W
a
y
H
a
n
d
s
h
a
k
i
n
g
:大多数实现
带有半关闭选项的四次握手
H
a
l
f
−
C
l
o
s
e
\begin{cases}三次握手Three-Way Handshaking:大多数实现\\带有半关闭选项的四次握手Half-Close\end{cases}
{三次握手Three−WayHandshaking:大多数实现带有半关闭选项的四次握手Half−Close
3.4.3.1 三次握手
(1)客户进程接收到关闭命令时,客户的TCP发送第一个段:FIN
段,FIN
段的FIN
被置位。
FIN段可以携带客户机要发送的最后一个数据块。或者只是一个控制段。只是一个控制段时仅占用一个序列号。
(2)服务器TCP接收到FIN段后,通知他的进程,并发送第二个段:FIN+ACK
段,证实它接收到来自客户端的FIN段,同时通告另一方连接关闭。这个段可以包含来自服务器的最后一个数据块。如果不携带数据,那么该段仅占用一个序列号。
(3)客户机TCP发送最后一段:ACK段。证实收到来自服务器的FIN段。包含了确认号,是来自服务器的FIN段的序号加1。该段不占用序列号。
![image-20211215180006525](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211215180006525.png)
3.4.3.2 带有半关闭的四次握手
half-close:当一端停止发送数据后,还可以继续接收数据。
任意一端可发送数据,但通常是由客户端发起的。
![image-20211215185217056](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211215185217056.png)
3.5 流量控制
TCP使用滑动窗口处理流量控制
3.5.1 特点
- TCP使用的滑动窗口协议介于Go-Back-N和Selective Repeat之间
- 不使用NAK,看起来像Go-Back-N帧协议
- 保存失序帧直到丢失的段到达
- TCP窗口的滑动窗口是面向字节的,数据链路层讨论的滑动窗口是面向帧的。
- TCP窗口大小可变,数据链路层的窗口大小是固定大小
3.5.2 TCP窗口
使用TCP窗口使数据传输更有效,同时控制数据流,使得目的端不至因为数据来得过多而瘫痪。TCP窗口是面向字节的。
滑动窗口的数据分类:
滑动窗口数据分类
{
左窗口外:已经发送且已经确认
窗口内
{
窗口内左侧:已经发送但未确认
窗口内右侧:可以立即发送
右窗口外:不满足发送条件,暂时不可发送
滑动窗口数据分类\begin{cases}左窗口外:已经发送且已经确认\\窗口内\begin{cases}窗口内左侧:已经发送但未确认\\窗口内右侧:可以立即发送\end{cases}\\右窗口外:不满足发送条件,暂时不可发送\end{cases}
滑动窗口数据分类⎩
⎨
⎧左窗口外:已经发送且已经确认窗口内{窗口内左侧:已经发送但未确认窗口内右侧:可以立即发送右窗口外:不满足发送条件,暂时不可发送
动作分类
{
c
l
o
s
i
n
g
:得到确认
o
p
e
n
i
n
g
:运行缓冲区存储符合发送条件的更新的字节
s
h
i
n
k
i
n
g
:废除某些符合条件的字节发送
动作分类\begin{cases}closing:得到确认\\opening:运行缓冲区存储符合发送条件的更新的字节\\shinking:废除某些符合条件的字节发送\end{cases}
动作分类⎩
⎨
⎧closing:得到确认opening:运行缓冲区存储符合发送条件的更新的字节shinking:废除某些符合条件的字节发送
3.5.3 窗口的大小
TCP窗口大小取决于两个值中较小的一个: min { r w n d , c w n d } \min\{rwnd, cwnd\} min{rwnd,cwnd}
- 接收窗口:在确认段中宣布的值
- 拥塞窗口:网络防止拥塞而确定的值
TCP的发送方不必发一个全窗口大小的数据。
TCP窗口的要点如下:
- 窗口大小是rwnd和cwnd中最小值
- 发送方不必发送一个全窗口大小的数据
- 接收方可张开或者合拢窗口,但是不能收缩窗口
- 只要不引起窗口收缩,目的方随时可以发送一个确认
- 接收方可以暂时关闭窗口,但在窗口关闭后发送方总是发送一个字节的段
4.TCP通知窗口
通知窗口是接收方根据接受能力确定的窗口。接收方将通知窗口的值放在报文首部发送给发送方。发送方根据接收方的工作状态改变窗口大小是TCP流量控制的主要方法。
如果接收方读取速度与到达速度一样,接收方在每一个确认中发送一个非零的窗口通告。如果发送方比接收方快,造成缓冲区全部被占用,那么接收方发送一个**“零窗口”通告**,发送方停止发送。直到收到一个非零窗口通告。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GDM2VVv8-1664536156901)(https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211215215602450.png)]
5.坚持计时器
非零窗口通告可能会丢失,TCP为每个连接设置了一个坚持计时器,当发送方收到零窗口确认时,就启动坚持计时器。计时器到期后,发送探测报文,提醒接收方确认报文已经丢失。
6.糊涂窗口综合征
如果TCP缓存已满,而应用进程每次只从缓存读取一个字节。向发送窗口发送为1的确认报文,此时发送方会以41字节的代价发送1字节的数据。这样下去,传输效率及低。
解决方法是禁止接收方发送只有1个字节的更新报文,接收方会等待一定的时间,使得收取缓存有足够空间接收一个较长的报文,再发送窗口更新报文。
3.6 差错控制
TCP的差错控制包括检测出报文的差错,丢失,失序和重复并纠正。
差错检测和纠正的方式
{
校验和
C
h
e
c
k
s
u
m
确认
A
c
k
n
o
w
l
e
d
g
e
重传
R
e
t
r
a
n
s
m
i
s
s
i
o
n
差错检测和纠正的方式\begin{cases}校验和Checksum\\确认Acknowledge\\重传Retransmission\end{cases}
差错检测和纠正的方式⎩
⎨
⎧校验和Checksum确认Acknowledge重传Retransmission
3.6.1 校验和
如果段受到损坏,那么将被目的端TCP丢弃,并且认为是丢失了。TCP在每段中强制使用一个16位的校验和。
3.6.2 ACK
TCP使用确认来证实已经收到了数据段。不携带数据但是占用序列号的一些控制段也要确认,但单独的ACK段是不需要确认的。
3.6.3 重传
3.6.3.1 RTO(retransmission time-out)后重传
- 重传计时器
TCP对所有重要的段(已经发送但是还未确认)使用一个重传超时计时器。
当计时器到时时,即使可能是由于段被延迟,ACK被延迟或者是ACK被丢失等未接收到ACK时,重发一个最早的重要的段。
仅仅含有ACK的段没有设置超时计时器,这样的段不需要重发。
- RTO计时器的值根据RTT更新
RTO的值是动态的,根据段的往返时间(Round-Trip Time)进行更新。
3.6.3.2 快速重传
收到3个重复的ACK。在重传计时器超时之前进行重传。
3.6.4 段的失序
当一个段被延迟、丢失或者废弃,后面到达的段就失序了。
{
T
C
P
原先设计:丢弃失序的段,并且重传失序段后面的段
T
C
P
现在设计:
{
不丢弃失序的段,标记他们为失序,直到缺少的段到达
这些失序的段不传递给进程,
T
C
P
确保数据按序传递给进程
\begin{cases}TCP原先设计:丢弃失序的段,并且重传失序段后面的段\\TCP现在设计:\begin{cases}不丢弃失序的段,标记他们为失序,直到缺少的段到达\\这些失序的段不传递给进程,TCP确保数据按序传递给进程\end{cases}\end{cases}
⎩
⎨
⎧TCP原先设计:丢弃失序的段,并且重传失序段后面的段TCP现在设计:{不丢弃失序的段,标记他们为失序,直到缺少的段到达这些失序的段不传递给进程,TCP确保数据按序传递给进程
3.6.5 TCP操作
3.6.5.1 一般操作
![image-20211218113004013](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211218113004013.png)
3.6.5.2 丢失的段
TCP对于丢失的段和损坏的段做同样的处理。
丢失段在网络某处丢失,损坏段被接收方本身丢弃。
![image-20211218113538639](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211218113538639.png)
TCP在间隙指明数据存在不连续性,在这个间隙被填充之前不将这个字节传递给应用程序。
3.6.5.3 快速重传
收到三个连续的同样序号的ACK时,不必等待RTO计时器过期,立即重传期待帧
![image-20211218113810826](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211218113810826.png)
3.7 拥塞控制
网络中的载荷即发送到网络中分组的数量,超过了网络的容量,在网络中就有可能发生拥塞。
3.7.1 拥塞窗口
发送方维护一个拥塞窗口cwnd,且动态变化。发送方让自己的发送窗口小于等于cwnd。
- 只要网络没有发生拥塞,拥塞窗口就再增大一些,以发送更多的分组。
- 假如发生拥塞,那么将拥塞窗口减小一些,减少到发送到网络中的分组数。
3.7.2 拥塞策略
TCP的拥塞策略基于三个阶段:
- 慢启动 slow start:以很慢的传输速率启动,迅速增大到阈值 threshold
- 拥塞避免 congestion avoidance:达到阈值后为避免拥塞降低数据速率
- 拥塞检测 congestion detection:检测到拥塞返回到慢启动或者拥塞避免
3.7.2.1 慢启动:指数增长
慢启动使用
- 指数增长,在一开始设置拥塞窗口cwnd为一个最大段长度MSS(连接建立时由最大长度选项决定)
- 每次收到一个确认,窗口大小增加一个MSS值。
窗口慢速启动,但是按照指数规则增长。
EXAMPLE:假设使用段的个数而不是字节的个数(好像每个段只有一个字节);
假定rwnd比cwnd大得多,这样发送窗口永远小于等于cwnd。
假设每个段都是单独确认的。
按照传输次数观察cwnd的大小(整个窗口中的段被确认),则发现其速率是按照指数的规则增长。数据增长的规律:
-
开始:cwnd = 1
-
第一次传输:cwnd = 2
-
第二次传输:cwnd = 4
-
第三次传输:cwnd = 8
![image-20211218150347020](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211218150347020.png)
如果有延迟的ACK,那么窗口的增长小于2的幂。
慢速启动不能一直持续下去,达到阈值时必须停止该阶段。发送方保存一个称为ssthresh(慢启动阈值)的变量。
当拥塞窗口中的字节达到阈值时,开始下一个阶段,ssthresh的值是2^16字节
3.7.2.2 拥塞避免:加性增加
拥塞避免的目的:在拥塞发生之前降低指数增长的速度。这个算法是加性增加,而不是指数增加。
加性增加:每次整个窗口的所有的段都被确认时,拥塞窗口才加1。(直到检测到数据丢失)
![image-20211218152857665](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211218152857665.png)
按照传输的次数观察cwnd的大小,则发现其速率是按照加性规律增长:
- 开始:cwnd = 1
- 第一次传输后:cwnd = 2
- 第二次传输后:cwnd = 3
- 第三次传输后:cwnd = 4
3.7.2.3 拥塞检测
能够检测到拥塞唯一方法是通过重传段的要求
{
严重情况:
R
T
O
计时器到期
接收到三个
A
C
K
\begin{cases}严重情况:RTO计时器到期\\接收到三个ACK\\\end{cases}
{严重情况:RTO计时器到期接收到三个ACK
RTO计时器到时:非常严重的拥塞的可能性
- TCP反应:
- 阈值减少到当前拥塞窗口大小的一半
- 设置cwnd为一个段的大小
- 启动慢速启动阶段
![image-20211218160359444](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211218160359444.png)
- 连续接收到三个ACK:存在轻度拥塞的可能性
- TCP反应:
- 阈值减少到当前拥塞窗口大小的一半
- 设置cwnd为阈值
- 启动拥塞避免阶段
- TCP反应:
![image-20211218160713294](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211218160713294.png)
策略总结:
策略
{
R
T
O
超时
{
阈值变为当前拥塞窗口大小一半
设置
c
w
n
d
为
1
个段的大小
开启慢启动状态
收到三个
A
C
K
{
阈值变为当前拥塞窗口的一半
拥塞窗口值为阈值
开启拥塞避免状态
策略\begin{cases}RTO超时\begin{cases}阈值变为当前拥塞窗口大小一半\\设置cwnd为1个段的大小\\开启慢启动状态\\\end{cases}\\收到三个ACK\begin{cases}阈值变为当前拥塞窗口的一半\\拥塞窗口值为阈值\\开启拥塞避免状态\end{cases}\end{cases}
策略⎩
⎨
⎧RTO超时⎩
⎨
⎧阈值变为当前拥塞窗口大小一半设置cwnd为1个段的大小开启慢启动状态收到三个ACK⎩
⎨
⎧阈值变为当前拥塞窗口的一半拥塞窗口值为阈值开启拥塞避免状态
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xy65vrBL-1664536156902)(https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211218161500989.png)]
4. SCTP 流控制传输协议
特点:
- 面向报文的可靠协议
- 兼具UDP和TCP的最佳特性
多流的概念:
![image-20211218161714676](https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211218161714676.png)
多端口的概念:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h8aMvXOb-1664536156902)(https://cdn.jsdelivr.net/gh/Holmes233666/gitee-image@main/pictureStore/image-20211218161829080.png)]
在SCTP中,数据大块按照传输序列号编号。控制信息和数据信息在分开的数据大块中携带。
为了别不同的流,SCTP使用SI。(流标识符)