Transport Layer

Posted by Vincent on May 7, 2021

[TOC]

运输层

面向通信的最高层,用户功能的最底层

传输层是只在主机才有的层次。像网络核心部分中的路由器,在转发的时候,都只用到下三层的功能。

image-20210507212654358

意义

网络层负责将包发送到主机,为主机之间提供逻辑通信。

传输层负责将包发送到进程,为应用进程之间提供端到端的逻辑通信

“逻辑通信”的意思是:从应用层来看,只要把应用层报文交给下面的运输层,运输层就可以把这报文传送到对方的运输层(那怕双方相距很远,例如几千公里),好像这种通信就是沿水平方向直接传送数据。但事实上这两个运输层之间并没有一条水平方向的物理连接。数据的传送是沿着图中的虚线方向(经过多个层次)传送的。

image-20210507213157082

基本功能

复用 (multiplexing)

发送方不同的应用进程都可以使用同一个运输层协议转送数据。

分用 (demultiplexing)

接收方的运输层在剥去报文的首部后能够把这些数据正确交付目的应用进程。

差错检测

网络层只检验首部,不检查数据部分。

实现

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

image-20210507213953959

UDP (用户数据报协议 / User Datagram Protocol)

特点

  1. 无连接的。

    不需要先建立连接。

  2. 尽最大努力交付。

    不需要维持复杂的连接状态表。

  3. 面向报文的。

    无论应用层传来多长的报文,UDP照样加上首部,再传给网络层。不做合并和拆分。(但是IP层会进行分片)

  4. 没有拥塞控制。

    适合允许丢失一些数据、而不能容忍时延的应用。 e.g. 要求主机以恒定速率发送数据的实时应用 (如 ip电话、实时视频会议)

  5. 支持1对1、1对多、多对1、多对多的交互通信。

  6. 首部开销小

    UDP : 8字节 (源端口、目的端口、长度、检验和)

    TCP : 20字节

优点

  1. 开销小
  2. 支持1对1、1对多、多对1、多对多的交互通信

缺点

  1. 不可靠
  2. 不做拆分,影响网络层的效率。
  3. 没有拥塞控制。最坏情况会使网络发生拥塞,结果大家都无法正常接收。

首部格式

image-20210507221240523

虽然UDP不可靠,不保证绝对交付。但是还是会做数据部分的校验的。

TCP (传输控制协议 / Transmission Control Protocol)

特点

  1. 需要先建立连接,结束要释放连接

  2. 一对一的。点对点的,不提供广播、多播服务

  3. 提供可靠的运输服务

  4. 全双工通信

  5. 面向字节流。 应用程序以数据块的形式交给TCP,但是TCP仅把它看成一串字节流。

    image-20210507222218749

优点

  1. 可靠

缺点

  1. 开销大。需要确认、流量控制、计时器以及连接管理等。

socket / 套接字

因为TCP协议既要点到点,又要不与操作系统有耦合,而且进程的创建和撤销都是动态的,所以尽管运输层是针对进程,也不能直接使用进程号作为终点。

于是乎,就采用了端口 (port),而应用程序也监听着端口,从而实现消费。

ip和port的组合就叫做socket。socket = (ip:port)

首部

image-20210509084842221

前20个字节固定,有额外40个字节扩展空间,以4字节为单位。

保证可靠性

要求

  1. 传输信道不产生差错。
  2. 不管发送方以多快的速度发送数据,接收方总是来得及处理收到的数据。

停止等待协议 / 自动重传请求 ARQ (Automatic Repeat reQuest)

每发送完一个分组就停止发送,等待对方的确认。在收到确认后再发送下一个分组。

  1. 必须暂时保留已发送分组的副本 (for 超时重传)
  2. 分组和确认分组都必须进行编号。 这样才能明确是哪个发送出去的分组收到了确认,而哪个分组还没收到确认。 因为有可能包没有丢失,只是延迟了很久,所以后面到达服务器的时候,服务器要判断编号,看是新的包还是旧的。
  3. 超时计时器设置的重传时间应当比数据在分组传输的平均往返时间更长一些。

优点

简单

缺点

信道利用率低

异常情况

  1. 数据有差错 接收方 : 丢弃。

    发送方 : 超时重传,需要在发送方中设置一个超时计时器,到时前收到对方的确认就撤销

    image-20210507223636081

  2. 确认丢失 接收方 : 丢弃,不向上层交付。向接收方发送确认 image-20210508221727722

  3. 确认迟到 发送方 : 丢弃

    接收方 : 丢弃重复的请求,重传确认

    image-20210508221747407

连续ARQ协议

发送方 : 窗口内并发发送

接收方 : 累计确认

image-20210509084233798

超时重传时间的选择

以上协议都设计到超时重传时间的设置,但是超时重传时间其实是很难把握的。

实际上采用自适应算法,记录报文段发出和收到确认的时间,并加权平均。

一旦报文被重传了,因为无法确定是哪个报文的重传,所以也就不采用其作为往返时间样本。再把重传时间增大一些

选择确认SACK (Selective ACK)

若收到的报文中间缺少一些序号的数据,选择确认SACK可以只传送缺少的数据,而不重传已经到达接收方的数据。

具体做法是 :

  • 依旧采用”确认号”字段,标识已经连续收到的最大边界。
  • 在首部加上”允许SACK”的选项。最多指明4个边界块 (因为一个边界块有2个边界,一个边界4个字节,一共32个字节。还有一个字节指明SACK选项,一个字节指明这个选项要占用多少字节)

滑动窗口

image-20210509100935488

作用

  • 流量控制
  • 性能优化 : 确认应答不再以每个分段,而是以更大的单位进行确认。

TCP缓存和窗口的关系

发送窗口其实是TCP缓存中的一小节,以指针确定边界。

image-20210509101117220

实现流量控制

流量控制就是让发送方别发那么快,让接收方来得及接收。

具体做法 :

  • 接收方回复发送方rwnd (reveiver window / 接收窗口) 的字节大小。发送方收到后调节。
  • 要是rwnd变为0
    • 接收方有空间的时候,会向发送方发送rwnd报文段
    • 发送方设有一个持续计时器,到时就发送探测报文段,如果还是0,就重设持续计时器(防止接收方的rwnd报文段丢失)

TCP的拥塞控制

拥塞控制 : 防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不至于过载。是一个全局性的过程。

和流量控制的区别

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

而拥塞控制是一个全局的问题,要做的是让整个网络不至于过载。

具体做法

  • 开环控制 : 在设计网络前,事先把导致拥塞的因素都考虑周到,一旦运行,不再干预。

  • 闭环控制 : 运行时干预

    • 监测网络系统
    • 把拥塞信息发送到可采取行动的地方
    • 调整网络系统的运行,以解决出现的问题

拥塞算法

  1. 慢开始 (slow-start) & 拥塞避免 (congestion avoidance)

    发送方维持一个拥塞窗口变量 cwnd (congestion window),并让自己的发送窗口等于拥塞窗口。

    只要网络没有出现拥塞 (没有收到确认报文),拥塞窗口就增大一点,反之减少。

    加法增大乘法减少 :

    image-20210509181921356

  2. 快重传 (fast retransmit) & 快恢复 (fast recovery)

    快重传 :

    收到失序报文后,接收方立刻发送确认号位置的重复确认。(让发送方及早知道没有到达的报文段)

    发送方一连收到3个重复确认,就应当立即重传对方尚未收到的报文段,而不必等到重传计时器到时。

    快恢复 :

    当发送方连续收到3个重复确认时,就执行”乘法减少”,预防网络拥塞

    image-20210509190330041

随机早期检测RED (Random Early Detection)

为了防止由于网络层导致拥塞,当路由器队列长度在最大和最小之间,按照一定概率将新到达的分组丢弃

三次握手

image-20210509192801313

为什么要第三次握手

一部分原因是检测双向联通,因为此时服务器端不确定client有收包的能力。

另一个原因是,防止网络不好的时候,client第一次发出去的请求延时了很久,导致一次连接可能client请求了很多次,但是有效的却只有一次。如果2次握手,那么server就需要打开多个连接,多余的连接server必须一直等待client发来数据,白白浪费资源。

四次挥手

image-20210509193331413

为什么server要发送2次

当server发送了第一次ack,此时TCP连接处于半关闭状态,TCP需要通知高层应用程序,这时候可以进行一些收尾工作。当server没有数据要发往client,此时TCP会再发送一次请求给client。

半关闭状态 : client没有数据要发送了,当server给client发送数据,client还是要接收)

为什么client要有持续2MSL (Maximum Segment Lifetime)的守寡期

  1. 因为client发送的最后一个ACK可能会丢失,那么server收不到client的 FIN + ACK,就会重发。而client要是立即释放连接,就无法收到这个重发了,这样server就无法释放连接,进入CLOSED状态
  2. 防止”已失效的连接请求报文段”出现在本连接中。在这2MSL的等待中,可以使这段时间内所产生的所有报文段在网络中消失。那么下一次新连接中就不会出现这种旧的连接请求报文段了。

保活计时器

连接建立后,要是client故障了,server收不到client的请求,便无法关闭连接。

所以server每收到一次client的请求,便会有重设保活计时器。

当到时间 (2小时),就会发送一个探测报文,再每隔75分钟发送一次。要是连续10次都没有收到client的response,就关闭连接。

TCP的有限状态机

图中每一个方框即TCP可能具有的状态。

每个方框中的大写英文字符串是TCP标准所使用的TCP连接状态名。

状态之间的箭头表示可能发生的状态变迁。

箭头旁边的字,表明引起这种变迁的原因,或表明发生状态变迁后又出现什么动作。

粗实线箭头表示对客户进程的正常变迁。

粗虚线箭头表示对服务器进程的正常变迁。

另一种细线箭头表示异常变迁。

image-20210509195916175