TCP/IP网络协议之传输层TCP

概述

运输层的功能

运输层向上面的应用层提供通信服务,确保网络中两个不同应用进程之间的可靠通信连接

运输层与网络层的区别

  • 网络层为主机之间提供逻辑通信,它只负责将某台主机发送的分组运送到其目的IP对应的主机上。在网络层,通信的两端的主体对象是主机。
  • 运输层为进程之间提供逻辑通信,它需要在数据到达主机后,根据其报文段上的目的端口号将数据交付到具体的进程中。在运输层,通信的两端主体对象是不同的进程。

运输层提供的功能

运输层提供的主要功能如下:

  • 为进程之间提供逻辑通信
  • 对收到的报文进行差错检测

运输层对应的协议

TCP/IP运输层的主要协议主要有两个:

  • 用户数据报协议UDP(User Datagram Protocol)
  • 传输控制协议TCP(Transmission Control Protocol)

下面是两者在协议栈中的位置
在这里插入图片描述

UDP和TCP的主要区别

  • UDP在传送数据前不需要先建立连接,并且UDP并不提供可靠交付。因此相较于TCP,UDP的效率更高
  • TCP提供面向连接的服务,在传送数据前必须先建立连接,数据传输结束后必须释放连接。因此,TCP相较于UDP不可避免地增加许多开销(确认、流量控制、连接管理等)。

端口号

所谓的端口,就好像是门牌号一样,客户端可以通过ip地址找到对应的服务器端,但是服务器端是有很多端口的,每个应用程序对应一个端口号,通过类似门牌号的端口号,客户端才能真正的访问到该服务器。为了对端口进行区分,将每个端口进行了编号,这就是端口号

使用端口号标识进程的原因

这部分我们通过解决问题的思路对使用端口号标识进程的原因进行分析。

首先需要通过某种方式来分辨不同的应用进程。

1. 使用PID标识进程

:PID与进程唯一对应
:不同的操作系统所使用的PID格式不同,为网络上不同进程的识别带来困难
举个例子,在中国,每个人都通过中文名字来标识不同的人。但是在美国,每个人的名字由英文字母组成,当我们需要与对方交流时,我们必须了解对方名称的写法以及读法。因此非常的不方便。

2. 使用一种统一的并且与操作系统无关的ID格式来标识进程

:能够统一网络层面上对进程标识符的格式。
:无法很好地识别进程,因为进程的创建与撤销是动态的,这意味着其对应的标识符会随着重新创建而发送变化,而对端无法及时获知这种变化。

3. 使用端口号来标识进程

端口号可以被应用进程主动绑定,也就是说,我每次打开同一个应用它都会具有相同的标识符,这解决了标识符随着进程创建和撤销带来的动态变化所导致的对端无法动态获知标识符变化。通过指定端口号,就能通过约定的形式知晓要将数据发送给哪个具体进程。

这种方式将进程本身与服务进行了分离,其中,不同的端口代表不同的服务。通过端口标识提供服务的入口,而无需了解具体提供服务的进程

端口号分类

端口号为16位,统一计算机最多有65535个端口号(-65536 ~ -1, 0~65535)

端口号分为下面两大类:

  • 服务器使用的端口号:数值为0~49151,通常这些端口号是为服务应用程序使用的
    • 熟知端口号/系统端口号:该端口号的数值范围为0~1023,这些端口号通过被指派给一些重要的应用程序,如FTP的21、HTTP的80等。
    • 登记端口号:数值为1024~49151,这类端口号是给一些没有熟知端口号的服务应用程序使用的,最熟悉的比如我们的Tomcat的8080端口号。
  • 客户端使用的端口号:数值为49152~65535,这些端口号通常仅在客户进程运行时才动态选择的,变化比较频繁。

用户数据报协议UDP

该协议仅在IP数据报服务上增加了复用/分用以及差错监测的功能。

UDP的主要特点

UDP的主要特点如下:

  • 面向无连接:不需要建立连接,因此减少了开销和发送数据前的时延。

  • 尽最大努力交付:即不保证可靠交付,假设对端有些数据丢失,也不会重发。

  • 面向报文:对应用层交下的报文不做任何操作,只添加首部。
    在这里插入图片描述

  • 没有拥塞控制

  • 支持1:1,1:N,N:N的交互通信

  • 首部开销小:只有8个字节,而TCP有20个

补充:使用UDP应用发送过多数据时,会造成网络拥塞,并造成数据丢失。可以通过应用层采用一些手段对这些特性进行弥补,如重传等



传输控制协议TCP


概述

TCP的主要特点

TCP的主要特点如下:

  • 面向连接:传送数据前需要先建立连接,在数据发送完毕后,释放已经建立的TCP连接。
  • 只能进行点对点的通信。
  • 提供可靠交付,确保传送的数据无差错、不丢失、不重复,并且按序到达。
  • 面向字节流

TCP的连接

每条TCP连接对应两个端点,而每个端点通过套接字(Socket)进行标识
套 接 字 s o c k e t = ( I P 地 址 : 端 口 号 ) 套接字socket = (IP地址:端口号) socket=(IP:)
每条TCP连接的唯一性由两个套接字确定
T C P 连 接 : : = { s o c k e t 1 , s o c k e t 2 } = { ( I P 1 : p o r t 1 ) , ( I P 2 : p o r t 2 ) } TCP连接 ::= \{socket_1, socket_2\} = \{(IP_1:port_1),(IP_2:port_2)\} TCP::={ socket1,socket2}={ (IP1:port1),(IP2:port2)}

现在socket也表示允许应用程序访问连网协议的应用编程接口API


TCP可靠传输

工作原理

TCP发送的报文段是交给IP层发送的。但IP层只能提供尽最大努力服务,也就是说TCP下面的网络提供的是不可靠的传输。因此TCP必须采用适当的措施才能使得两个运输层之间的通信变得可靠

理想的传输条件包含以下特征:

  • 传输信道不产生差错
  • 发送方的发送速度不会超出接收方的接收能力

可靠传输的实现

具体的可靠传输的实现就是在解决理想传输条件所对应的难题。事实上这个问题是通过ARQ(Automatic Repeat-reQuest,ARQ)协议解决的

自动重传请求(Automatic Repeat-reQuest,ARQ)是OSI模型中数据链路层的错误纠正协议之一。它包括停止等待ARQ协议和连续ARQ协议,错误侦测(Error Detection)、正面确认(Positive Acknowledgment)、逾时重传(Retransmission after Timeout)与负面确认继以重传(Negative Acknowledgment and Retransmission)等机制。

停止等待ARQ协议

该协议的目的就是实现传输信道不产生差错这样特征

原理
A:发送方;B:接收方

  1. B收到A发送的分组当回复确认
  2. A等待B的回复,若超时则认为B未收到分组,重发分组
  3. B收到重复分组则丢弃。并返回收到确认

:逻辑简单
:信道利用率太低(A的下一分组的发送必须等到B的回复确认)
在这里插入图片描述
TD:发送分组所需时间
TA:发送确认分组所需时间
RTT:往返时间
信 道 利 用 率 U = T D T D + R T T + T A 信道利用率U = \frac{T_D}{T_D + RTT + T_A} U=TD+RTT+TATD

连续ARQ协议

该协议的目的是实现发送方的发送速度不会超出接收方的接收能力。同时也是对停止等待协议劣势的弥补

原理
A:发送方;B:接收方
通过窗口滑动一次性发送多个分组,B累计收到的分组,并对按序到达的最后一个分组发送确认。当A收到确认将根据收到的分组号号进行窗口滑动,发送下一分组。
在这里插入图片描述
当线路质量不好时,会造成信道资源的大量浪费。因为我们发现一旦中间某个分组丢失,其往后所有的分组都会被重传

超时重传时间的选择

前面提到,当TCP发送方在规定时间内未收到回复则认为需要重传已发送的报文段。但是超时时间如何计算。

TCP采用一种自适应算法,具体的计算公式如下
新 的 R T T S = ( 1 − α ) ∗ ( 旧 的 R T T S ) + α ∗ ( 新 的 R T T 样 本 ) 新的RTT_S = ( 1- α ) * (旧的RTT_S) + α * (新的RTT样本) RTTS=(1α)(RTTS)+α(RTT)
α:表示新的RTTS受新RTT样本影响的权重,α越大,则受新RTT样本影响越大(0 ≤ α ≤ 1),该值的推荐值为1/8
RTTS:加权平均往返时间
RTT:往返时间
超 时 重 传 时 间 R T O = R T T S + 4 ∗ R T T D 超时重传时间RTO = RTT_S + 4 * RTT_D RTO=RTTS+4RTTD
RTTD:RTT的偏差的加权平均值,它的变化受新RTT样本以及RTTS之间的差值影响。
新 的 R T T D = ( 1 − β ) ∗ ( 旧 的 R T T D ) + β ∗ ( R T T S − 新 的 R T T 样 本 ) 新的RTT_D = ( 1- β ) * (旧的RTT_D) + β * ( RTT_S - 新的RTT样本) RTTD=(1β)(RTTD)+β(RTTSRTT)
β:表示新的RTTD受新RTT样本影响的权重,β越大,则受新RTT样本影响越大(0 ≤ β ≤ 1),该值的推荐值为1/4

超时重传时间的选择算法中存在的问题

超时重传时间的选择算法中存在一个问题,那就是如果一个报文段被重发,那么我们如何判断收到的回复对应的是重发的报文还是旧的报文。能否正确地判断对确定加权平均RTTS的值关系很大。

TCP的做法是,一旦发生重传,就将RTO延长(典型的作发为延长两倍),而不使用原有的RTO计算公式

TCP报文段首部格式

TCP报文段的首部长度为20个字节
在这里插入图片描述

首部字段解释

  • 源端口号(2字节)
  • 目标端口号(2字节)
  • 序号(4字节):标识当前的分组序号
  • 确认号(4字节):用来标识期望收到对方下一个报文段的第一个数据字节的序号(期待的下一分组序号)
  • 数据偏移(4字节):TCP报文段的数据起始处距离报文段的开始位置有多远
  • 保留(6字节):全0
  • 紧急URG:为1时表示数据紧急,优先发送。不需要按照原有的排队顺序进行发送。
  • 确认ACK(Acknowledgment) :建立连接后所有传输的报文段都需要设置为1
  • 推送PSH:为1时,数据不会等到缓存满了之后才发送。而是立即发送
  • 复位RST:为1时表示TCP连接出现严重差错,需要释放连接然后重新连接。
  • 同步SYN:在连接时用来同步序号。SYN=1,ACK=0时表示连接请求报文;SYN=1,ACK=1表示同意连接的响应报文
  • 终止FIN:用来释放一个连接。为1时表示数据发送完毕,请求释放运输连接
  • 窗口(2字节):表示接收方的接收窗口大小
  • 校验和(2字节):用于差错检测
  • 紧急指针(2字节):在URG=1时有效,指出本报文段中的紧急字节数,在TCP缓冲区的最后。
  • 选项(长度可变):
    • 最大报文段长度MSS(Maximum Segment Size)
    • 窗口扩大选项(3字节):接收窗口 = 窗口 + 窗口扩大
    • 时间戳:用于计算RTT以及防止序号绕回(用于区分序号绕回后新序号报文与原同序号的迟到报文区分开)
    • SACK选择确认选项:用于告诉发送方丢失的分组范围,从而避免序号丢失后后面那些已收到的数据的重复发送。如果需要使用SACK,需要在TCP建立连接时,在TCP首部的选项中加入允许SACK的选项

TCP的流量控制

目的

让发送方的发送速率不超过接收方的接受速率

实现方式

使用滑动窗口机制,由接收方发送的确认报文中的窗口数值来控制发送方的发送速率,从而控制流量。建立连接时,接收方告诉发送发自身接收窗口的大小。发送发根据将根据这个窗口大小限制自身的发送窗口大小
在这里插入图片描述
问题
当rwnd=0的回复报文段被A接收后,A不再发送任何报文段,转而等待B发送新的rwnd。假设此时B发送了一个新的rwnd,但是这个报文段丢失了,那么此时就会陷入死锁状态。A在等待B的新窗口值,而B在等待A的新数据。
解决
A在收到rwnd=0的回复报文段后会开始计时,超时则向B发送一个探测报文。B在收到探测报文后会根据情况给出新窗口值

TCP的发送时机

  1. 达到最长报文段长度MSS
  2. 应用进程主动push
  3. 发送方的计时期限到达

TCP的拥塞控制

目的

防止过多的数据注入到网络中,这样可以使得网络中的路由器/链路不过载。

拥塞产生的原因

引起网络拥塞的主要原因如下:

  1. 节点缓存小,到达该节点的多余的数据被丢弃,造成发送方不断超时不断重发。换句话说,网络处理不了的量不断被推迟,随着时间增长,这个量不会断上升。
  2. 节点处理速度太慢,造成过长的排队时延,引发超时重发,增加网络拥塞状况

针对前面的原因有以下几种解决方案

  1. 扩大节点缓存,该方案看似解决第一个问题,实则不可取。因为缓存小只是造成网络拥塞的直接原因而非真实原因,真实原因是无限制的网络输入引起节点的缓存不足。同时,增大缓存会导致排队时延增加,从而导致超时,发送发不断重传,产生恶性循环。
  2. 提升节点的处理速度,该方案能够一定程度缓解问题,但是治标不治本
  3. 平衡网络各部分之间的交互,该方案旨在根据网络情况去将网络的流量平衡在一个相对稳定的部分。

拥塞控制与流量控制的区别

流量控制关注的是点对点的问题,其所做的只是平衡发送者与接收这之间的处理能力。但是拥塞控制关注的是整个网络的输入负载与网络承受能力之间的关系,而非仅限于某几个特定网络输入。两者的相同之处在于都是向发送方发送控制报文,让发送方控制发送速率来达成目的。

输入负载与吞吐量之间的关系

下面是负载与吞吐量之间的关系图
在这里插入图片描述

理想:吞吐量在达到上限前与输入负载持平,无丢包。并在发送拥塞后保持原有极限吞吐量
实际:随着输入负载上升,网络就开始出现丢包,其吞吐量的增长速率开始下降
无控制:当网络严重堵塞时会发现死锁,导致网络基本处于瘫痪状态

TCP的拥塞控制方案

TCP进行拥塞控制的算法有四种,其原理是基于拥塞窗口大小发送报文段,拥塞窗口大小取决于网络的拥堵程度。

假设:
(1) 数据是单向的,对方只传送确认报文
(2) 接收方总是拥有足够大的缓存空间,因而发送窗口有网络的拥塞程度控制

1.慢开始

思路
设置较小的发生窗口。根据收到的确认报文数量动态增加拥塞窗口打算小。理论上,只要不出现丢包。每经过一个传输轮次(cwnd允许的报文发送完毕,知道最后一个字节确认),拥塞窗口加倍。

:不会在一开始输入太多报文段,而是根据确认报文段呈指数增长(这种增长存在上限,由ssthresh字段控制)

2.拥塞避免

思路
在慢开始中拥塞窗口到达ssthresh值时开始转换为平稳的线性增长,从而避免增长过快造成网络拥堵。当网络出现拥塞时(判断条件是出现超时),重置ssthresh为当前拥塞窗口大小的1/2,并重置拥塞窗口,重新进入慢开始

:很大程度上避免了慢开始后期的指数增长所引发的网络拥塞的可能性。

3.快重传

目的
该算法旨在解决由于个别报文段丢失(并非网络拥塞引起的报文段丢失)所引起的超时重置慢开始(降低了网络传输速率)。采用该算法可以让发送方尽早知道发送个别报文段的丢失。

思路
当接收方发现丢失个别报文段后,立即发送确认。即使收到失序的报文段也要立即发出对已收到的报文的重复确认。举例,接收方收到M1,M2,M4,M5四个报文段,丢失了M3报文段。在分别收到M4,M5时会立即发送对M2的确认报文段。也就是说发送方会受到两个M2的确认报文。

:不必等到达到某个报文段发送条件才会发送确认报文,尽可能早地让发送方知道丢包情况。从而避免发送方重置慢开始

4.快恢复

当发送方获得多个连续的重复确认时可以获知只是丢失个别报文段,于是不启动慢开始,而是执行快恢复算法

思路

  1. 调整门限值ssthresh = cwnd/2
  2. cwnd = ssthresh
  3. 执行拥塞避免算法

主动队列管理AQM(Active Queue Management)、

该算法并不属于传输层,而是网络层出于解决传输层的一些问题而出现的
出现原因
由于路由器通常采用尾部丢弃策略,导致一连串分组的丢失。由于多条TCP复用一个IP发送,因此一连串分组的丢失会导致多条TCP连接同时发生超时,并同时进入慢开始。这被称为全局同步
全局同步造成的结果为全网通信量突然出现大规模的降低,而在恢复后又迅速大规模增长,再次造成拥塞。

AQM解决思路
设置警惕上限,达到该上限后路由器采取随机丢弃策略

总结

总的来说,TCP的拥塞控制采用了AIMD算法来控制输入负载。

AIMD算法分为AI(Additive Increase)加法增大算法和MD(Multiplicative Decrease)乘法减小算法

发送窗口的大小取决于下面公式
发 送 窗 口 大 小 = M i n [ r w n d , c w n d ] 发送窗口大小 = Min[rwnd,cwnd] =Min[rwnd,cwnd]
rwnd:接收窗口
cwnd:拥塞窗口


TCP的运输连接管理

TCP连接分为三个阶段:

  1. 连接建立
  2. 数据传送
  3. 连接释放

TCP的运输连接管理的目的就是使得运输连接的建立和释放都能够正常地进行。

连接建立(三次握手)

下面介绍连接建立的三次握手过程。
在这里插入图片描述

  1. 主机A发送连接请求报文段,(SYN=1,ACK=0时表示连接请求报文)
  2. 主机B向A发送连接确认报文,同意此次连接(SYN=1,ACK=1时表示同意连接的响应报文)
  3. 主机A向B发送确认报文。此时双方连接建立完成,可以传输数据

问题:当B向A发送连接同意的响应报文时,应当可以认为连接建立完成了,为什么还需A最后再发送一次确认?

回答:防止失效的连接请求报文段突然又发送到B。假设现在只需要前两次握手即可建立连接,当A发送了一个连接请求后发现超时,因此认为无法连接,转而下线。此时B收到了迟到的连接请求,B主机误认为A请求连接,因此发出了同意连接,表示此次连接建立成功。但事实上,主机A早就已经下线,因此本次成功的连接事实上是失败的。但是主机B却不断等待主机A发送数据,浪费了许多资源。而采用三次握手可以避免这个问题。

连接释放(四次握手)

在这里插入图片描述

  1. A向B发起释放连接请求(FIN=1),此时表示A没有数据可以发送了,TCP连接处于半关闭状态。但是此时依旧需要接受来自B的数据。因为B到A的连接尚未关闭。
  2. A收到来自B的确认后就进入终止等待,等待B发出的连接释放报文段。
  3. 若B此时没有需要向A发送的数据了,其应用程序据通知TCP释放连接。此时B向A发送连接释放请求(FIN=1,ACK=1) 。此时B进入最后等待确认状态,等待A的释放确认
  4. 当收到A的释放确认后,B正式关闭连接
  5. 但是此时A还需要持续保存连接一段时间,原因有两个:
    (1)防止迟到的请求连接报文再次建立连接。
    (2)防止最后的确认报文超时,导致B由于未收到确认报文段,长时间不关闭连接

猜你喜欢

转载自blog.csdn.net/qq_33905217/article/details/113928304