本章讨论 TCP/IP 体系中运输层最重要的两种协议 TCP/UDP.

1, 进程间的通信

运输层向它上面的应用层提供通信服务。两个主机间的通信实际上是两个主机应用进程间的通信。通信的真正端点不是主机而是主机间的进程。

运输层有个很重要的功能,复用和分用,这里的复用是指在发送方不同的应用进程中都可以使用同一个运输层协议传递数据 (加上适当的头部),分用是指接收方的运输层在剥去报文的首部后,能把这些数据正确的交给目的的应用进程。

逻辑通信的意思是:运输层之间的通信好像沿着水平方向传送数据,但是实际上这两个运输层之间并没有一条水平方向的物理连接。要传送的数据是沿着图中虚线的方向经过多个层次传输的。

网络层为主机之间提供逻辑通信,运输层为应用进程之间提供端到端的逻辑通信。

运输层还要对收到的报文进行差错检测。

根据应用程序的不同要求,运输层提供面向连接的 TCP 和无连接的 UDP。

运输层向高层用户屏蔽了下面的网络细节 (如网络拓扑,所采用的路由选择协议),它使得应用进程看见的就好像在两个运输层实体之间好像有一条端到端的逻辑通信信道。

2,运输层的两个协议 TCP/UDP

UDP 在传输数据前不需要建立连接,远地的主机的运输层在收到 UDP 报文后,不需要给出任何确认。

TCP 则提供面向连接的服务,在传输数据之前要建立连接,传输完数据后要释放连接。

应用层的所有应用进程都可以通过运输层再传送到 IP 层,这就是复用。运输层从 IP 层收到数据后必须交付给指明的应用进程,这就是分用。

在运输层使用协议端口号,简称端口号,来区分应用层的进程。

在协议栈层间的抽象的协议端口是软件端口。而软件端口是应用层的各种协议进程与运输层实体进行层间交互的一种软件地址。

端口号只具有本地意义,只是为了标志本计算机的应用层的各个进程在和运输层交互时的层间接口。

3.UDP 概述

特点:

(1) UDP 是无连接的。

(2) UDP 使用尽最大努力交付,不保证可靠交付。

(3) UDP 是面向报文的,应用层交付的报文不进行拆分,所以应用进程要选择合适的报文大小。

(4) UDP 没有拥塞控制。

(5) UDP 支持一对一,一对多,多对一,多对多的交互通信。

(6) UDP 的首部开销小。

4,UDP 的数据报格式

(1) 源端口号。在需要对方回信是选用,不需要时为 0.

(2) 目的端口号。在终点交付报文时要用到。

(3) 长度。UDP 数据报的长度,其最小值为 8.

(4) 检验和。检测 UDP 数据报在传输过程中是否有错,有错就丢弃。

5,TCP 的最主要的特点

(1) TCP 是面向连接的运输层的协议。

(2) 每一条 TCP 连接只能有两个端点。每条 TCP 连接只能是点对点的。、

(3) TCP 提供可靠交付的服务。

(4) TCP 提供全双工通信

(5) 面向字节流。

TCP 中的 “流” 是指流入到进程或从进程中流出的字节序列。面向字节流的含义是:虽然应用程序和 TCP 的交互是一次一个数据块,但是 TCP 把应用程序交下来的数据仅仅看成是一串无结构的字节流。

6,TCP 的连接

端口号拼接到 IP 地址就构成了套接字。套接字 socket::=(IP 地址,端口号)。

每一条 TCP 连接唯一的被通信的两个端点 (即套接字) 所确定:

TCP 连接::={socket1,socket2}={(IP1,port1),(IP2,port2)}

TCP 连接的端点是套接字,即 (IP 地址,端口号)。也还应记住:同一个 IP 地址可以有多个不同的 TCP 连接,而同一个端口号也可以出现在多个不同的 TCP 连接中。

7,可靠工作的原理

(1) 停止等待协议

1, 无差错的情况:发送端发送 M1,接收端在收到 M1 后,发送确认,然后发送方发送 M2。依次往后。

2, 出现差错:发送方只要超过了一段时间仍然没有收到确认,就认为刚才发送的分组丢失了,因而重传前面发送过的分组,这就叫超时重传,要实现超时重传就要在每发送完一个分组后设置一个超时计时器。

注意的三点:

第一, 发送方在发送完一个分组后,必须暂时保留已发送分组的副本 (为超时重传使用),只有在收到相应的确认后后才能清除暂时保留的分组副本。

第二, 分组和确认分组都必须编号,这样才能确定是哪一个发出去的分组收到了确认,而哪一个分组还没有收到确认。

第三, 超时计时器设置的重传时间应当比数据在分钟传输的平均往返时间更长一些。运输层的重传时间是非常复杂的,因为分组到底经过哪些网络和会产生多大的时延是不确定的。

3, 确认丢失和确认迟到

采取两个行动:(1) 丢弃重复的分组,不向上层交付。(2) 向发送方发送确认。

自动重传请求:重传的请求是自动进行的,接收方不需要请求发送方重传某个分组。

4, 信道利用率 U=

TD: 发送分组所用的时间。RTT 是分组往返一次的时间。TA 是发送确认的时间。

当往返时间 RTT 远大于分组发送时间 TD 时信道的利用率就会很低。

为了提高传输效率,我们采用了流水线传输。流水线传输:发送方可以连续发送多个分组,不必每发送一个分组就停顿下来等待对方的确认。这样可以使信道上一直有数据不间断地在传送,显然这种传输方式可以获得很高的信道利用率。

5, 连续的 ARQ 协议

Go-back-N:表示要再退回来重传已经发送过的 N 个分组,可见当通信线路质量不好时,连续的的 ARQ 协议会带来负面影响。

8,TCP 报文段的首部格式

(1) 源端口和目的端口 各 2 个字节

(2) 序号占 4 个字节 TCP 连接中传送的字节流中每个字节都按顺序编号,首部中的序号字段值则指的是本报文段所发送的数据的第一个字节的序号。

(3) 确认号占 4 个字节 是期望收到对方下一个报文段的第一个数据字节的序号。

(4) 数据偏移占 4 位,它指出了 TCP 报文段数据起始处距离 TCP 报文段的起始处有多远。即 TCP 报文段的首部长度。

(5) 保留占 6 位

(6) 紧急 (URG) 当 URG=1 时,表明紧急指针有效,告诉系统此报文段中有紧急数据。应尽快传送。而不要按照原来的排队顺序来传送。当 TCP 有紧急数据时,就把紧急数据插入本报文段数据的最前面,而在紧急数据后面的数据仍然是普通数据。这时要与首部的紧急指针配合使用。

(7) 确认 ACK 仅当 ACK=1 时,确认字段有效。TCP 规定:在建立连接之后,所有数据报的 ACK 字段都为 1.

(8) 推送 PSH 在两个进程通信的过程中,如果一个进程希望另一个进程及时作出反应,则将 PSH 字段置为 1. 不过推送操作很少用。

(9) 复位 RST RST=1,可以用来表明 TCP 连接出现差错,或者拒绝非法报文段和非法连接。

(10) 同步 SYN 在建立连接时用来同步序号。

(11) 终止 FIN 用来释放一个连接。

(12) 窗口占 2 字节。窗口指的是发送报文一端的数据接收窗口大小。窗口值作为接收方让发送方设置其发送窗口的依据。

(13) 检验和占 2 字节。检验和字段检验范围包括首部和数据两个部分。和 UDP 数据报一样。在计算检验和时要加上伪首部。要把伪首部第 4 个字段中的 17 改为 6.

(14) 紧急指针占 2 字节。在 URG=1 时才有意义。即使窗口为 0 时,也可以发送紧急数据。

(15) 选项长度可变,最长可达 40 字节。

最初只有最大报文段长度 (MSS) 用来指出 TCP 报文段的数据部分的长度。

   后来又增加了窗口扩大选项,时间戳选项等。

   窗口扩大选项:为了扩大窗口, 占 3 个字节。

   时间戳选项:占 10 个字节包括时间戳值,4 个字节和时间戳回送回答,4 个字节。

   两个功能:1,用来计算往返时间 RTT。2,用来处理 TCP 序号超过的情况,也称防止序号绕回。

9,TCP 可靠传输的实现。

(1) 以字节为单位的滑动窗口

TCP 的滑动窗口是以字节为单位的。在发送端有一个发送窗口。维持三个指针 1,数据发送起始指针 Ps(point of the start),2. 未发送数据起始指针 Puss(point of unsend start)。3,可以发送数据的终止指针 Pe(point of end)。

关系:Pe-Ps = 发送端的发送窗口

  Puss-Pe = 已经发送的数据

  Pe-Puss = 可以发送但是还没有发送的数据。

过程:

(1) Puss 的起始值为 Ps。在发送过程中,随着数据的发送,Puss 一直再向 Pe 移动,但是不会大于 Pe。当 Puss 等于 Pe 的时候表示发送窗口的数据都发送出去了。

(2) 当发送窗口中的所有数据都被正确接收时,Ps=Pe。Puss=Ps;Ps=Ps + 接收窗口大小。

要注意的几点:

(1) 虽然 A 的发送窗口是根据 B 的接收窗口设置的,但在同一时刻,A 的发送窗口和 B 的接收窗口并不总是一样大。

(2) 对于不按序到达的数据报怎么处理,TCP 标准并无明确规定。因此 TCP 通常对不按序到达的数据是先临时存放在接收窗口中,等字节流中所缺少的字节到达后,再按序交付给上层的应用进程。

(3) TCP 要求接收方必须有累积确认的功能,这样可以减少传输开销。可以直接发送确认或者在自己有数据的时候捎带上。注意:1,接收方不应过分推迟发送确认,否则会导致发送方不必要的重传。2,捎带确认实际上并不经常发生,因为大多数应用程序不同时在两个方向上发送数据。

10,超时重传时间的选择。ααα

TCP 采用了一种自适应算法,他记录一个报文发出的时间以及收到相应确认的时间,这两个时间之差就是报文段的往返时间 RTT。TCP 保留了一个 RTT 的加权平均往返时间 RTTs.

新的 RTT 的计算方法 RTTs(new)=(1-α)RTTs(old)+ αx 新的 RTT 样本。α推荐值 0.125;

超时重传时间 RTO=RTTs+4*RTβββββββTD。RTTD 是 RTT 的加权平均值。

新的 RTTD=(1-β)* 旧的 RTTD+β*|RTTs—- 新的 RTT 样本 |β推荐值 0.25;

改进的地方:在计算加权平均值 RTTs 时,只要报文段重传了,就不采用其往返时间样本。这样得出的加权平均值 RTTs 和 RTO 就比较准确。报完段每重传一次,就把超时重传时间 RTO 增大一些。典型的做法是取新的重传时间为旧的重传时间的 2 倍。

11,考虑 TCP 传输的效率

在发送端可以采取的三种常用方法:(1)TCP 维持一个变量,当缓存中的数据等于该变量的值时,就发送数据。(2), 由发送方指明要发送的数据,TCP 进行推送操作。(3), 发送方维持一个计时器,当时间到了,发送方就把缓存中的数据发送出去。

当发送方发送数据较少较慢:发送方先发送一个字节的数据,然后把后面到达的数据缓存起来。当发送方收到第一个字节的确认后,就可以把后面的数据发送过去了。

糊涂窗口综合症 (接收方处理的慢):让接收方等待一段时间,使得接收方有一定的缓存来存放 接收的数据。当然发送方也不要有一点数据就发送。

12,TCP 的拥塞控制

拥塞:在某段时间内,若对网络中的某一资源的需求超过了该资源所能提供的可用部分,网络的性能就可能变坏,这种情况就叫做拥塞。

问题的实质:整个系统的各个部分不匹配,只有所有的部分平衡了,问题才能解决。

拥塞常趋于恶化。

拥塞控制和流量控制的关系:拥塞控制是防止过多的数据注入网络中,这样可以使网络中的路由器或者链路不至于过载。流量控制是指点到点的通信量的控制,是个端到端的问题。

当网络的吞吐量明显小于理想的吞吐量时,网络就进入了轻度拥塞状态。当提供的负载达到某一数值时,网络的吞吐量反而随着负载的增加而下降,这时网络就进入了拥塞状态。当提供的负载继续增大到某一数值时,网络的吞吐量就下降到 0,网络已无法工作,这就是所谓的死锁。

在许多情况下,甚至是拥塞控制机制本身成为引起这个网络性能恶化甚至发生死锁的原因。

13,几种拥塞控制的方法

(1) 慢开始和拥塞避免

发送方维持一个叫做拥塞窗口的变量,拥塞窗口的大小取决于网络的拥塞程度,并且动态的变化,发送方让自己发送窗口等于拥塞窗口。

发送方控制拥塞窗口的原则:只要网络没有拥塞,就增大窗口,要是发现了拥塞,就缩小窗口。

慢开始算法:由小到大的增大发送窗口,即由小到大的增加拥塞窗口,发送方每收到一个队分组的确认,就使发送方的拥塞窗口加倍。类似于启动阶段,速度小,加速度大。

拥塞避免:让拥塞窗口缓慢的增大,即每经过一个往返时间 RTT 就把发送方的拥塞窗口加 1,这样拥塞窗口 cwnd 按照线性规律缓慢增长。类似于速度大,加速度小。

(2), 快重传和快恢复。

快重传算法首先要求接收方每收到一个失序的报文段后就立即发送重复确认 (为得是使发送方及早知道有报文没到达对方),而不要等待自己发送数据时才捎带确认。

快重传算法规定:发送方只要一连收到三个重复的确认就的当立即重传对方未收到的报文段,而不必等待为该报文段设置的定时器超时,由于发送方尽早重传未发送的报文段,因此采用快重传后可以使整个网络的吞吐量提高 20%。

与快重传配合使用的还有快恢复算法:

(1) 当发送方连续收到三个重复的确认时,就执行乘法减小算法,把慢开始门限减半,这是为了预防网络发生拥塞,注意:接下去不执行慢开始算法。

(2) 由于发送方现在认为网络很有可能发生了拥塞,因此与慢开始算法不同之处是现在不执行慢开始算法,而是把 cwnd 的值设为慢开始门限 sstresh 减半后的数值,然后开始执行拥塞避免算法 (加法增大), 使拥塞窗口缓慢地线性增大。

发送方的发送窗口一定不能超过对方给定的接收窗口的值。

14,随机早期检测

当路由器由于分组太多无法处理而丢弃分组的情况下,若发生了路由器中的尾部丢弃,则可能会同时影响到很多条 TCP 连接,结果是这么多的 TCP 的连接在同一时间进入慢开始状态。这在 TCP 术语中称为全局同步。在网络恢复正常后通信量又突然增大。

所谓随机早期检测:就是在网络还没有发生拥塞的时候,以预测的方法避免出现拥塞。

在快出现拥塞的时候,就以一定的概率丢弃分组,以便使发送方提前减少数据的发送,避免发生拥塞。所以问题的关键就在什么时候以多大的概率丢弃分组。

15,TCP 的运输连接管理

运输连接分为三个阶段:连接建立,数据传送,连接释放。

TCP 的连接释放:

为什么客户端的 TIME-WAIT 状态必须等待 2MSL 的时间?

第一, 为了保证 A 发送的最后一个 ACK 报文可以到达服务器

第二, 防止已经失效的报文段出现在本连接中。