3.0 运输层

[TOC]

概述

功能: 运输层协议为运行在不同的主机上的应用进程提供了逻辑通信功能。网络层提供了主机之间的逻辑通信。

多路复用 多路分解

多路分解:将运输层报文段中的数据交付到正确的套接字
多路复用:源主机从不同套接字中收集数据块,并为每个数据块封装首部信息生成报文段,传递到网络层,这些工作成为多路复用。

无连接运输:UDP

特点

  • 无连接的
    发送方和接收方的运输层实体之间没有握手。不会引入建立连接的时延。

  • 无连接状态
    TCP需要在端系统中维护连接状态,包括接收和发送给缓存、拥塞控制参数以及序号和确认号的参数。

  • 分组首部开销小

  • 关于何时、发送什么数据的应用层控制更为精细
    UDP打包即发出,没有TCP的拥塞控制等限制,TCP可靠交付可能时延比较大。

  • 面向数据报

为什么说TCP报文段是面向字节流的,UDP是面向数据报的?

面向报文的传输方式是应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。因此,应用程序必须选择合适大小的报文。若报文太长,则IP层需要分片,降低效率。若太短,会是IP太小。UDP对应用层交下来的报文,既不合并,也不拆分,而是保留这些报文的边界。这也就是说,应用层交给UDP多长的报文,UDP就照样发送,即一次发送一个报文。

虽然应用程序和TCP的交互是一次一个数据块(大小不等),但TCP把应用程序看成是一连串的无结构的字节流。TCP有一个缓冲,当应用程序传送的数据块太长,TCP就可以把它划分短一些再传送。如果应用程序一次只发送一个字节,TCP也可以等待积累有足够多的字节后再构成报文段发送出去。

在TCP建立连接前两次握手的SYN报文中选项字段的MSS值,通信双方商定通信的最大报文长度。如果应用层交付下来的数据过大,就会对数据分段,然后发送;否则通过滑动窗口协议来控制通信双发的数据。

报文

提供端到端的差错检测,但是对差错恢复无能为力,有点UDP的实现是丢弃受损的报文段,其他实现是将受损的报文段交给应用程序并给出警告。

UDP和TCP的不同

面向连接的运输:TCP

特点

  • 面向连接可靠运输
  • 全双工服务
    进程A和B建立连接,应用层数据可在从进程B流向进程A的同时,也从进程A流向进程B。
  • 点对点
    连接在单个发送方和单个接收方之间。
  • 面向字节流

维基百科TCP

MSS

TCP三次握手初期设置发送缓存,TCP从发送缓存里取数据,从缓存取出并放到报文段的数据数量受限于 最大报文段长度(Maximum Segment Size, MSS)

MSS通常根据MTU设置。MSS保证一个TCP报文段适合MTU(报文+TCP/IP首部)。MSS典型值 1460字节。

报文

TCP首部通常20字节。

连接管理

三次握手

参考 TCP的三次握手与四次挥手

  • TCP服务器进程先创建传输控制块TCB,时刻准备接受客户进程的连接请求,此时服务器就进入了LISTEN(监听)状态;
  • TCP客户进程也是先创建传输控制块TCB,然后向服务器发出连接请求报文,这是报文首部中的同部位SYN=1,同时选择一个初始序列号 seq=x ,此时,TCP客户端进程进入了 SYN-SENT(同步已发送状态)状态。TCP规定,SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号。
  • TCP服务器收到请求报文后,如果同意连接,则发出确认报文。确认报文中应该 ACK=1,SYN=1,确认号是ack=x+1,同时也要为自己初始化一个序列号 seq=y,此时,TCP服务器进程进入了SYN-RCVD(同步收到)状态。这个报文也不能携带数据,但是同样要消耗一个序号。
  • TCP客户进程收到确认后,还要向服务器给出确认。确认报文的ACK=1,ack=y+1,自己的序列号seq=x+1,此时,TCP连接建立,客户端进入ESTABLISHED(已建立连接)状态。TCP规定,ACK报文段可以携带数据,但是如果不携带数据则不消耗序号。
  • 当服务器收到客户端的确认后也进入ESTABLISHED状态,此后双方就可以开始通信了。

为什么需要三次握手而不是两次握手?

一句话,主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。

如果使用的是两次握手建立连接,假设有这样一种场景,客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了,由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。此时此前滞留的那一次请求连接,网络通畅了到达了服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。

如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。

也可以这样理解,
第一次 只能确认发送方发送正常
第二次 能确认接收方发送接收正常,发送方发送正常,但还无法确认发送方接收正常
第三次 能确认双方接收发送都正常

四次挥手

  • 客户端进程发出连接释放报文,并且停止发送数据。释放数据报文首部,FIN=1,其序列号为seq=u(等于前面已经传送过来的数据的最后一个字节的序号加1),此时,客户端进入FIN-WAIT-1(终止等待1)状态。 TCP规定,FIN报文段即使不携带数据,也要消耗一个序号。
  • 服务器收到连接释放报文,发出确认报文,ACK=1,ack=u+1,并且带上自己的序列号seq=v,此时,服务端就进入了CLOSE-WAIT(关闭等待)状态。TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
  • 客户端收到服务器的确认请求后,此时,客户端就进入FIN-WAIT-2(终止等待2)状态,等待服务器发送连接释放报文 (在这之前还需要接受服务器发送的最后的数据)。
  • 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,由于在半关闭状态,服务器很可能又发送了一些数据,假定此时的序列号为seq=w,此时,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
  • 客户端收到服务器的连接释放报文后,必须发出确认,ACK=1,ack=w+1,而自己的序列号是seq=u+1,此时,客户端就进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2*MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
  • 服务器只要收到了客户端发出的确认,立即进入CLOSED状态。同样,撤销TCB后,就结束了这次的TCP连接。可以看到,服务器结束TCP连接的时间要比客户端早一些。

为什么客户端最后还要等待2MSL?

MSL(Maximum Segment Lifetime),TCP允许不同的实现可以设置不同的MSL值。

第一,保证客户端发送的最后一个ACK报文能够到达服务器,因为这个ACK报文可能丢失,站在服务器的角度看来,我已经发送了FIN+ACK报文请求断开了,客户端还没有给我回应,应该是我发送的请求断开报文它没有收到,于是服务器又会重新发送一次,而客户端就能在这个2MSL时间段内收到这个重传的报文,接着给出回应报文,并且会重启2MSL计时器。

第二,防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失。这样新的连接中不会出现旧连接的请求报文。

为什么建立连接是三次握手,关闭连接却是四次挥手呢?

建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。

可靠性传输

ARQ

ARQ(Automatic Repeat reQuest)自动重传请求协议 是OSI模型数据链路层和运输层的错误纠正协议之一。通过确认超时这两个机制,在不可靠服务的基础上实现可靠的信息传输。包括停止等待ARQ协议连续ARQ协议

TCP使用的是连续ARQ协议。

ARQ协议包括这些机制

  • 差错检测
  • 接收方反馈 肯定确认ACK、否定确认NCK
    • 累计确认: 接收方不必对收到的分组逐个发送确认。而是在收到几个分组后,对按序到达的最后一个分组发送确认。
  • 重传 超时重传等

ARQ协议对错误纠正的方法是:

  • 丢弃已经接收的含有错误的数据包。
  • 向发送点请求重新发送数据包。

可参考维基百科ARQ

连续ARQ

为了克服停止并等待ARQ协议长时间等待ACK的缺点。这个协议会连续发送一组数据包(流水线传输),然后再等待这些数据包的ACK.

流水线传输就是发送方可以连续发送多个分组,不必每发完一个分组就停下来等待对方确认。连续ARQ通常结合滑动窗口协议使用。

回退N重传(Go-Back-N)

  • 接收点丢弃从第一个没有收到的数据包开始的所有数据包。
  • 发送点收到NACK后,从NACK中指明的数据包开始重新发送。
    • 有缺点:不能正确的向发送方反映出接收方已经正确收到的所以分组的信息。
    • 比如发送方发送了前5个分组,而中间的第3个分组丢失了,这时候接收方只能对前2个发出确认。而不知道后面3个分组的下落,因此只能把后面的3个分组都重传一次,

选择重传(Selective Repeat)

  • 发送点连续发送数据包但对每个数据包都设有个一个计时器。
  • 当在一定时间内没有收到某个数据包的ACK时,发送点只重新发送那个没有ACK的数据包。

停止等待ARQ

停止并等待协议的工作原理如下:

  • 发送点对接收点发送数据包,然后等待接收点回复ACK并且开始计时。
  • 在等待过程中,发送点停止发送新的数据包。
  • 当数据包没有成功被接收点接收时候,接收点不会发送ACK.这样发送点在等待一定时间后,重新发送数据包。
  • 反复以上步骤直到收到从接收点发送的ACK.

缺点

  • 较长的等待时间导致低的数据传输速度

滑动窗口

发送方维护发送窗口,接收方维护接收窗口。

规则:

  • (1)凡是已经发送过的数据,在未收到确认之前,都必须暂时保留,以便在超时重传时使用。
  • (2)只有当发送方A收到了接收方的确认报文段时,发送方窗口才可以向前滑动几个序号。
  • (3)当发送方A发送的数据经过一段时间没有收到确认(由超时计时器控制),就要使用回退N步协议,回到最后接收到确认号的地方,重新发送这部分数据。

发送窗口中有四个概念

  • 已发送并收到确认的数据(不在发送窗口和发送缓冲区之内)
  • 已发送但未收到确认的数据(位于发送窗口之内)
  • 允许发送但尚未发送的数据(位于发送窗口之内)
  • 发送窗口之外的缓冲区内暂时不允许发送的数据。

接收窗口中也有四个概念

  • 已发送确认并交付主机的数据(不在接收窗口和接收缓冲区之内)
  • 未按序收到的数据(位于接收窗口之内)
  • 允许的数据(位于接收窗口之内)
  • 不允许接收的数据(位于发送窗口之内)。

流量控制

一条TCP连接每一侧主机都为该连接设置了接受缓存。TCP连接收到正确、按序的字节后,它就将数据放入接收缓存。应用程序从该缓存读数据,但不是数据刚到就读取。为了防止发送方发送太多太快,导致接收缓存溢出,TCP提供流量控制服务(flow-control service)

使用滑动窗口协议

发送方维护 接收窗口(rwnd) 的变量进行流量控制。

把rwnd的值放在TCP报文 接收窗口字段。

举例:

拥塞控制 (TCP conggestion control algorithm)

和流量控制相似,都是控制发送方发送的速度,但是目标不一样,流量控制是为了防止接收方接收缓存溢出,拥塞控制是因为网络发生拥堵而降低发送速度。

TCP的拥塞控制采用了四种算法,即 慢开始 、 拥塞避免 、快重传 和 快恢复。

可参考

慢开始

发送方维持一个叫做 拥塞窗口cwnd(congestion window) 的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞窗口,另外考虑到接受方的接收能力,发送窗口可能小于拥塞窗口。

慢开始算法的思路就是,不要一开始就发送大量的数据,先探测一下网络的拥塞程度,也就是说由小到大逐渐增加拥塞窗口的大小 (乘法增长)

这里用报文段的个数的拥塞窗口大小举例说明慢开始算法,实时拥塞窗口大小是以字节为单位的。如下图:

拥塞避免

为了防止cwnd增长过大引起网络拥塞,还需设置一个 慢开始门限ssthresh状态变量。ssthresh的用法如下:

  • 当cwnd < ssthresh时,使用慢开始算法。
  • 当cwnd > ssthresh时,改用拥塞避免算法。
  • 当cwnd = ssthresh时,慢开始与拥塞避免算法任意。

无论是在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞,就把 慢开始门限设置为出现拥塞时的发送窗口大小的一半。然后把拥塞窗口设置为1,执行慢开始算法。

快重传 和 快恢复 (FRR, fast retransmit and recovery)

快重传要求接收方在收到一个失序的报文段后就立即发出重复确认(为的是使发送方及早知道有报文段没有到达对方)而不要等到自己发送数据时捎带确认。快重传算法规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段,而不必继续等待设置的重传计时器时间到期(没有FRR,如果数据包丢失了,TCP 将会使用定时器来要求传输暂停。在暂停的这段时间内,没有新的或复制的数据包被发送)。

快重传配合使用的还有快恢复算法,有以下两个要点:

  • ①当发送方连续收到三个重复确认时,就执行“乘法减小”算法,把ssthresh门限减半。但是接下去并不执行慢开始算法。
  • ②考虑到如果网络出现拥塞的话就不会收到好几个重复的确认,所以发送方现在认为网络可能没有出现拥塞。所以此时不执行慢开始算法,而是将cwnd设置为ssthresh的大小,然后执行拥塞避免算法。

应用层协议使用运输层协议一些分类

  • SSH
    端口号22,TCP
  • MYSQL
    端口号 3306 TCP

0~1023是周知端口号,受限制,给HTTP或者FTP这种预留使用的。