运输层

运输层是整个网络体系结构的关键层次之一,在面试中也是高频考点。包括协议特点、进程之间通信和端口等概念,比较简单的UDP协议,复杂但十分重要的TCP协议和可靠传输的工作原理,包括停止等待协议和ARQ协议。以及三个重要问题:滑动窗口、流量控制和拥塞控制机制。还有TCP三次握手四次挥手过程。

运输层协议概述

运输层的作用

  • 从运输层的角度看,通信的真正端点并不是主机而是主机中的进程。也就是说,端到端的通信是应用进程之间的通信。
  • 在一台主机中经常有多个应用进程同时分别和另一台主机中的多个应用进程通信,这表明运输层有一个很重要的功能——复用和**分用 **。
    • 复用:指在发送方不同应用进程都可以使用同一个运输层协议传送数据(当然要加上适当的首部)。
    • 分用:指接收方的运输层在剥去报文的首部后能够把这些数据正确交付目的应用进程。
  • 网络层为主机之间提供逻辑通信,而运输层为应用进程之间提供端到端的逻辑通信。
  • 这条逻辑通信信道对上层的表现却因运输层使用的不同协议而有很大的差别。当运输层采用面向连接的 TCP 协议时,尽管下面的网络是不可靠的(只提供尽最大努力服务),但这种逻辑通信信道就相当于一条全双工的可靠信道。当运输层采用无连接的 UDP 协议时,这种逻辑通信信道是一条不可靠信道。

运输层的端口

  • 端口用一个 16 位端口号进行标志。可允许有65535个不同的端口。
  • 端口号只具有本地意义,即端口号只是为了标志本计算机应用层中的各进程。不同计算机的相同端口号是没有联系的。

服务器端使用的端口号

  • 熟知端口,数值一般为 0~1023。IANA把这些端口号指派给了TCP/IP最重要的一些应用程序,让所有用户都知道。比如HTTP使用的端口号是80,DNS是53.
  • 登记端口:数值为 1024~49151,为没有熟知端口号的应用程序使用的。使用这个范围的端口号必须在 IANA 登记,以防止重复。

常用的熟知端口

客户端使用的端口号

  • 又称为短暂端口号,数值为 49152~65535,留给客户进程选择暂时使用。当服务器进程收到客户进程的报文时,就知道了客户进程所使用的动态端口号。通信结束后,这个端口号可供其他客户进程以后使用。

用户数据报协议UDP

UDP概述

UDP 只在 IP 的数据报服务之上增加了很少一点的功能:

  1. 复用和分用的功能
  2. 差错检测的功能

虽然 UDP 用户数据报只能提供不可靠的交付,但 UDP 在某些方面有其特殊的优点。

重要特点

  • UDP 是无连接的,发送数据之前不需要建立连接,因此减少了开销和发送数据之前的时延。
  • UDP 使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的连接状态表。
  • UDP 是面向报文的。UDP 对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。UDP 一次交付一个完整的报文。因此,应用程序需选择合适大小的报文,若报文太长,UDP把它交给IP层时可能需要分片,降低IP层的效率,若太短,交给IP层后会使IP数据报首部相对长度太大,也降低IP层的效率。
  • UDP 没有拥塞控制,因此网络出现的拥塞不会使源主机的发送速率降低。这对某些实时应用是很重要的。很适合多媒体通信的要求。
  • UDP 支持一对一、一对多、多对一和多对多的交互通信。
  • UDP 的首部开销小,只有 8 个字节,比 TCP 的 20 个字节的首部要短。

UDP首部格式

用户数据报 UDP 有两个字段:数据字段和首部字段。首部字段很简单,只有 8 个字节。

  • 源端口:源端口号。在需要对方回信时使用。不需要时可全为0.
  • 目的端口:目的端口号。
  • 长度:UDP用户数据报的长度,其最小值为8,仅有首部。
  • 检验和:检验UDP用户数据报在传输中是否有错,有错就丢弃。

当运输层从 IP 层收到 UDP 数据报时,就根据首部中的目的端口,把 UDP 数据报通过相应的端口,上交最后的终点——应用进程。如果接收方UDP发现收到的报文中目的端口号不正确,即不存在对应于该端口的应用进程,就丢弃该报文,并由网际报文控制协议ICMP发送“端口不可达”差错报文给发送方。

虽然在 UDP 之间的通信要用到其端口号,但由于 UDP 的通信是无连接的,因此不需要使用套接字。

在计算检验和时,临时把“伪首部”和 UDP 用户数据报连接在一起。伪首部仅仅是为了计算检验和。UDP的检验和是把首部和数据部分一起都检验。而IP协议只检验首部。

一些使用UDP的例子:

  1. 应用层协议中DNS,也就是根据域名解析IP地址的一个协议,使用的就是UDP。
  2. DHCP,这个是给各电脑分配IP地址的协议,其中用的也是UDP协议。
  3. IGMP,我们说的多播,也就是使用的UDP,在多媒体教室,老师拿笔记本讲课,我们在下面通过各自的电脑看到老师的画面,这就是通过UDP传输数据,所以会出现有的同学卡,有的同学很流畅,就是因为其不可靠传输,但是卡一下,对接下来的观看并没有什么影响。

传输控制协议TCP

TCP是面向连接的运输层协议,提供可靠交付、全双工通信,面向字节流,有流量控制、拥塞控制。每一条TCP连接只有两个端点。TCP连接的端点叫**套接字(socket)**。表示方法是(IP地址:端口号),每一条TCP连接唯一地被通信两端的两个套接字所确定。

TCP报文段首部格式

  • 源端口和目的端口字段:各占 2 字节。端口是运输层与应用层的服务接口。运输层的复用和分用功能都要通过端口才能实现。
  • 序号字段:占 4 字节。TCP 连接中传送的数据流中的每一个字节都编上一个序号。序号字段的值则指的是本报文段所发送的数据的第一个字节的序号
  • 确认号字段:占 4 字节,是期望收到对方的下一个报文段的数据的第一个字节的序号。确认号为N,表明到序号N-1的所有数据都已正确收到
  • 数据偏移(即首部长度):占 4 位,它指出 TCP 报文段的数据起始处距离 TCP 报文段的起始处有多远。“数据偏移”的单位是 32 位字(以 4 字节为计算单位)。
  • 确认 ACK :只有当 ACK = 1 时确认号字段才有效。当 ACK = 0 时,确认号无效。
  • 同步 SYN :同步 SYN = 1 表示这是一个连接请求或连接接受报文。,在进行三次握手时和ACK配合使用。
  • 终止 FIN :用来释放一个连接。FIN = 1 表明此报文段的发送端的数据已发送完毕,并要求释放运输连接。在释放连接时使用。
  • 窗口字段 :占 2 字节,指发送本报文段一方的接收窗口,用来让对方设置发送窗口的依据,单位为字节。
  • 检验和:占 2 字节。检验和字段检验的范围包括首部和数据这两部分。在计算检验和时,要在 TCP 报文段的前面加上 12 字节的伪首部。
  • 选项字段:长度可变。TCP 最初只规定了一种选项,即最大报文段长度 MSS。MSS是数据字段的最大长度。

TCP可靠传输的实现

滑动窗口协议

发送方维持的发送窗口,它的意义是:位于发送窗口内的分组都可连续发送出去,而不需要等待对方的确认。连续 ARQ 协议规定,发送方每收到一个确认,就把发送窗口向前滑动一个分组的位置。接收方一般采用累积确认的方式。即不必对收到的分组逐个发送确认,而是对按序到达的最后一个分组发送确认,这样就表示:到这个分组为止的所有分组都已正确收到了

以字节为单位的滑动窗口

TCP的滑动窗口是以字节为单位的。

现假定 A 收到了 B 发来的确认报文段,其中窗口是 20 字节,而确认号是 31(这表明 B 期望收到的下一个序号是 31,而序号 30 为止的数据已经收到了)。根据这两个数据,A 就构造出自己的发送窗口。

发送窗口表示:在没有收到 B 的确认的情况下,A 可以连续把窗口内的数据都发送出去。显然,窗口越大,发送方就可以在收到对方确认之前连续发送更多的数据,因而可能获得更高的传输效率。

假设A发送了序号为31-41的数据

B收到了序号为32和33的数据,但没有按序到达,因为序号为31的数据没有收到,因此B发送的确认报文段的确认号仍然是31,即期望收到的序号。

假定B收到了序号为31的数据,接着把接收窗口向前移动三个序号。

A收到B的确认后,就可以把发送窗口向前滑动三个序号,但指针P2不变,A的可用窗口增大了。

A在继续发送完序号42-53的数据后,指针P2向前移动和P3重合。但没有收到确认。由于此时A的发送窗口已满,可用窗口为零,必须停止发送,但还没有收到确认。为了保证可靠传输,A在经过一段时间(由超时计时器控制)就重传这部分数据,重新设置超时计时器,直到收到B的确认为止。

发送缓存

发送方的应用进程把字节流写入 TCP 的发送缓存。

接收缓存

接收方的应用进程从 TCP 的接收缓存中读取字节流。

超时重传时间的选择

TCP 每发送一个报文段,就对这个报文段设置一次计时器。

只要计时器设置的重传时间到但还没有收到确认,就要重传这一报文段。

选择确认SACK

若收到的报文段无差错,只是未按序号,中间还缺少一些序号的数据,那么通过选择确认SACK可以只传送缺少的数据而不重传已经正确到达接收方的数据。

然而,由于SACK文档并没有指明发送方应当怎样响应SACK,因此大多数的实现还是重传所有未被确认的数据块。

TCP流量控制

利用滑动窗口实现流量控制

流量控制 (flow control) 就是让发送方的发送速率不要太快,既要让接收方来得及接收,也不要使网络发生拥塞。利用滑动窗口机制可以很方便地在 TCP 连接上实现流量控制。

可变窗口进行流量控制举例

B进行了三次流量控制。第一次把窗口减小到rwnd=300,第二次减到rwnd=100,最后减到rwnd=0,即不允许再发送数据。

但是可能会发生死锁。比如B 向 A 发送了零窗口的报文段后不久,B 的接收缓存又有了一些存储空间。于是 B 向 A 发送了 rwnd = 400 的报文段。但这个报文段在传送过程中丢失了。A 一直等待收到 B 发送的非零窗口的通知,而 B 也一直等待 A 发送的数据。

为了解决这个问题,TCP 为每一个连接设有一个持续计时器 (persistence timer)。只要 TCP 连接的一方收到对方的零窗口通知,就启动该持续计时器。若持续计时器设置的时间到期,就发送一个零窗口探测报文段(仅携带 1 字节的数据),而对方就在确认这个探测报文段时给出了现在的窗口值。若窗口仍然是零,则收到这个报文段的一方就重新设置持续计时器。若窗口不是零,就可以继续传输数据了。

TCP传输效率

可以用不同的机制来控制 TCP 报文段的发送时机

  • 第一种机制是TCP 维持一个变量,它等于最大报文段长度 MSS。只要缓存中存放的数据达到 MSS 字节时,就组装成一个 TCP 报文段发送出去。
  • 第二种机制是由发送方的应用进程指明要求发送报文段,即 TCP 支持的推送 (push)操作。
  • 第三种机制是发送方的一个计时器期限到了,这时就把当前已有的缓存数据装入报文段(但长度不能超过 MSS)发送出去。

TCP拥塞控制

对网络中某资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏。这种现象称为拥塞。若网络中有许多资源同时产生拥塞,网络的性能就要明显变坏,整个网络的吞吐量将随输入负荷的增大而下降。

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

拥塞控制就是防止过多的数据注入到网络中,使网络中的路由器或链路不致过载。拥塞控制是一个全局性的过程,涉及到所有的主机、所有的路由器,以及与降低网络传输性能有关的所有因素。

流量控制往往指点对点通信量的控制,是个端到端的问题(接收端控制发送端)。流量控制所要做的就是抑制发送端发送数据的速率,以便使接收端来得及接收。

TCP进行拥塞控制的算法有四种:慢开始,拥塞避免、快重传、快恢复。假定:

  1. 数据是单方向传送的,对方只传送确认报文。
  2. 接收方总是有足够大的缓存空间,因此发送窗口的大小由网络拥塞程度决定。

慢开始

发送方维持一个叫做拥塞窗口cwnd的状态变量,动态地在变化。发送方让自己的发送窗口等于拥塞窗口。判断网络拥塞的依据是出现了超时

算法的思路:由小到大逐渐增大拥塞窗口数值。

慢开始门限 ssthresh(状态变量):防止拥塞窗口cwnd 增长过大引起网络拥塞。

发送方每接收到一个报文的确认,cwnd就增加一。所以每经过一个传输轮次 ,拥塞窗口 cwnd 就加倍。

慢开始门限 ssthresh 的用法如下:

  • 当 cwnd < ssthresh 时,使用慢开始算法。
  • 当 cwnd > ssthresh 时,停止使用慢开始算法而改用拥塞避免算法。
  • 当 cwnd = ssthresh 时,既可使用慢开始算法,也可使用拥塞避免算法。

拥塞避免

让拥塞窗口 cwnd 缓慢地增大,即每经过一个往返时间 RTT 就把发送方的拥塞窗口 cwnd 加 1,而不是加倍,使拥塞窗口 cwnd 按线性规律缓慢增长。

当网络出现了超时,就要使ssthresh = cwnd/2,同时cwnd置为1,执行慢开始算法。

慢开始和拥塞避免算法的实现举例

当拥塞窗口cwnd = 16时(图中的点④),出现了一个新的情况,就是发送方一连收到 3 个对同一个报文段的重复确认(图中记为3-ACK)。发送方改为执行快重传和快恢复算法。

快重传

发送方只要一连收到三个重复确认,就知道接收方确实没有收到报文段,因而应当立即进行重传(即“快重传”),这样就不会出现超时,发送方也不就会误认为出现了网络拥塞。

快恢复

当发送端收到连续三个重复的确认时,由于发送方现在认为网络很可能没有发生拥塞,因此现在不执行慢开始算法,而是执行快恢复算法 FR (Fast Recovery) 算法:

  1. 慢开始门限 ssthresh = 当前拥塞窗口 cwnd / 2 ;
  2. 新拥塞窗口 cwnd = 慢开始门限 ssthresh ;
  3. 开始执行拥塞避免算法,使拥塞窗口缓慢地线性增大。

综上,TCP的拥塞控制流程如下

发送窗口的上限值

发送方的发送窗口的上限值应当取为接收方窗口 rwnd 和拥塞窗口 cwnd 这两个变量中较小的一个。

当 rwnd < cwnd 时,是接收方的接收能力限制发送窗口的最大值。

当 cwnd < rwnd 时,则是网络的拥塞限制发送窗口的最大值。

rwnd 和 cwnd 中数值较小的一个,控制了发送方发送数据的速率。

TCP的连接建立

  • TCP 建立连接的过程叫做握手。
  • 握手需要在客户和服务器之间交换三个 TCP 报文段。称之为三报文握手。
  • 采用三报文握手主要是为了防止已失效的连接请求报文段突然又传送到了,因而产生错误。
  1. A 的 TCP 向 B 发出连接请求报文段,其首部中的同步位 SYN = 1,并选择序号 seq = x,表明传送数据时的第一个数据字节的序号是 x。
  2. B 的 TCP 收到连接请求报文段后,如同意,则发回确认。B 在确认报文段中应使 SYN = 1,使 ACK = 1,其确认号ack = x + 1,自己选择的序号 seq = y。
  3. A 收到此报文段后向 B 给出确认,其 ACK = 1,确认号 ack = y + 1。A 的 TCP 通知上层应用进程,连接已经建立。

A为什么最后还要发送一次确认呢?

主要是为了防止已失效的连接请求报文段突然又传送到了B。

假设没有第三次握手,客户端发送一个连接请求报文过去,但是因为网络延迟,在等待了一个超时时间后,客户端就会在重新发一个请求连接报文过去,然后正常的进行,服务器端发回一个确认连接报文,然后就开始通讯,通讯结束后,释放连接。但一次发送的请求报文段这时到达了服务器,服务器端不知道这个报文已经失效,也发回了一个确认连接报文,客户端接收后,发现自己并没有发送连接请求(因为超时了,所以就认为自己没有发),所以对这个确认连接请求就什么也不做,但是此时服务器端不这么认为,他认为连接已经建立了,就一直打开着等待客户端传数据过来,服务器的许多资源就被浪费。

采用三报文握手,A不会向B发送确认,B由于收不到确认,就知道A没有请求建立连接。

TCP的连接释放

TCP 连接释放过程是四报文挥手。

  1. A 的应用进程先向其 TCP 发出连接释放报文段,并停止再发送数据,主动关闭 TCP 连接。A 把连接释放报文段首部的 FIN = 1,其序号seq = u,它等于前面已传送过的数据的最后一个字节的序号加1。这时A进入FIN-WAIT(终止等待1)状态,等待B的确认。
  2. B 发出确认,确认号 ack = u + 1,而这个报文段自己的序号 seq = v。TCP 服务器进程通知高层应用进程。从 A 到 B 这个方向的连接就释放了,TCP 连接处于半关闭状态。B到A这个方向的连接并未关闭,这个状态可能会持续一段时间。B 若发送数据,A 仍要接收。
  3. 若 B 已经没有要向 A 发送的数据,其应用进程就通知 TCP 释放连接。B还必须重复上次已发送过的确认号。这时B就进入LAST-ACK(最后确认)状态,等待A的确认。
  4. A在收到B的连接释放报文后,对此发出确认。ACK=1,ack=w+1,seq=u+1,进入到TIME-WAIT(时间等待)状态。这时TCP连接还没有释放掉,必须经过时间等待计时器设置的2MSL后,A才进入到CLOSED状态
  5. B在收到确认后就进入CLOSED状态。

A必须等待2MSL时间的原因

  1. 为了保证 A 发送的最后一个 ACK 报文段能够到达 B。B收到了确认报文,才能进入CLOSED状态。
  2. 防止 “已失效的连接请求报文段”出现在本连接中。A 在发送完最后一个 ACK 报文段后,再经过时间 2MSL,就可以使本连接持续的时间内所产生的所有报文段,都从网络中消失。这样就可以使下一个新的连接中不会出现这种旧的连接请求报文段。
Author

叶润繁

Posted on

2022-01-18

Licensed under