目录
运输层
概述和运输层服务
运输层协议为运行在不同主机上的应用进程之间提供了逻辑通信(logic communica-tion)功能。应用进程使用运输层提供的逻辑通信功能彼此发送报文,而无须考虑承载这些报文的物理基础设施的细节。
运输层协议是在端系统中而不是在路由器中实现的。
在发送端,运输层将从发送应用程序进程接收到的报文转换成运输层分组,用因特网术语来讲该分组称为运输层报文段(segment)。传递给网络层,网路层将其封装成网络层分组(即数据报)并向目的地发送。
在接收端,网络层从数据报中提取运输层报文段,并将该报文段向上交给运输层。运输层则处理接收到的报文段,使该报文段中的数据为接收应用进程使用。
因特网有两种协议,即 TCP 和UDP。每种协议都能为调用的应用程序提供一组不同的运输层服务。
运输层和网络层的关系
网络层提供了主机之间的逻辑通信,而运输层为运行在不同主机上的进程之间提供了逻辑通信。
因特网运输层概述
UDP(用户数据报协议),它为调用它的应用程序提供了一种不可靠、无连接的服务。TCP(传输控制协议),它为调用它的应用程序提供了一种可靠的、面向连接的服务。
因特网网络层协议有一个名字叫 IP,即网际协议。IP 为主机之间提供了逻辑通信。IP 的服务模型是尽力而为交付服务(best-effort delivery serv-ice)。它不确保报文段的交付,不保证报文段的按序交付,不保证报文段中数据的完整性。由于这些原因,IP 被称为不可靠服务(unreliable service)。
UDP和 TCP最基本的责任是,将两个端系统间IP 的交付服务扩展为运行在端系统上的两个进程之间的交付服务。将主机间交付扩展到进程间交付被称为运输层的多路复用(transport-layer multiplexing)与多路分解(demultiplexing)。
TCP为应用程序提供了几种附加服务。首先,它提供可靠数据传输(relia-ble data transfer)。通过使用流量控制、序号、确认和定时器(本章将详细介绍这些技术),TCP确保正确地、按序地将数据从发送进程交付给接收进程。这样,TCP 就将两个端系统间的不可靠 IP服务转换成了一种进程间的可靠数据传输服务。TCP 还提供拥塞控制 (con-gestion control)。TCP拥塞控制防止任何一条 TCP连接用过多流量来淹没通信主机之间的链路和交换设备。TCP 力求为每个通过一条拥塞网络链路的连接平等地共享网络链路带宽。这可以通过调节 TCP 连接的发送端发送进网络的流量速率来做到。
UDP流量是不可调节的。使用 UDP传输的应用程序可以根据其需要以其愿意的任何速率发送数据。
多路复用与多路分解
一个进程(作为网络应用的一部分)有一个或多个套接字(socket),它相当于从网络向进程传递数据和从进程向网络传递数据的门户。在接收于机中的运输层实际上并没有直接将数据交付给进程。而是将数据交给了一个中间的套接字。每个套接字都有唯一的标识符。标识符的格式取决于它是 UDP还是 TCP套接字。
将运输层报文段中的数据交付到正确的套接字的工作称为多路分解(demultiplexing)。在源主机从不同套接字中收集数据块,并为每个数据块封装上首部信息(这将在以后用于分解)从而生成报文段,然后将报文段传递到网络层,所有这些工作称为多路复用(multiplexing)。
运输层多路复用要求∶①套接字有唯一标识符;②每个报文段有特殊字段来指示该报文段所要交付到的套接字。
在主机 上的每个套接字能够分配一个端口号,当报文段到达主机时,运输层检查报文段中的目的端口号,并将其定向到相应的套接字。然后报文段中的数据通过套接字进入其所连接的进程。
无连接的多路复用与多路分解
创建一个 UDP套接字∶ clientSocket = socket(AF_INET,SOCK_DGRAM) 当用这种方式创建一个 UDP套接字时,运输层自动地为该套接字分配一个端口号。
另外一种方法是,在创建一个套接字后,我们能够在 Python 程序中增加一行代码,通过套接字 bind()方法为这个UDP套接字关联一个特定的端口号(如 19157)∶ clientSocket.bind(('',19157))
面向连接的多路复用与多路分解
TCP套接字是由一个四元组(源IP地址,源端口号,目的 IP地址,目的端口号)来标识的。
该主机使用全部4个值来将报文段定向(分解)到相应的套接字。特别与UDP不同的是,两个具有不同源IP 地址或源端口号的到达 TCP报文段将被定向到两个不同的套接字,除非 TCP 报文段携带了初始创建连接的请求。
Web 服务器与TCP
在端口 80上运行一个Apache Web服务器。当客户(如浏览器)向该服务器发送报文段时。所有报文段的目的端口都将为80。该服务器能够根据源IP地址和源端口号来区分来自不同客户的报文段。
无连接运输∶UDP
UDP只是做了运输协议能够做的最少工作。除了复用/分解功能及少量的差错检测外。它几平没有对 IP增加别的东西。UDP 从应用进程得到数据,附加上用干多路复用/分解服务的源和目的端口号字段、以及两个其他的小字段,然后将形成的报文段交给网络层。
网络层将该运输层报文段封装到一个IP 数据报中,然后尽力而为地尝试将此报文段交付给接收主机。如果该报文段到达接收主机,UDP使用目的端口号将报文段中的数据交付给正确的应用进程。
使用 UDP 时,在发送报文段之前,发送方和接收方的运输层实体之间没有握手。正因为如此,UDP被称为是无连接的。
DNS是一个通常使用 UDP的应用层协议的例子。
有许多应用更适合用UDP,原因主要以下几点∶
● 关于发送什么数据以及何时发送的应用层控制更为精细。
● 无须连接建立。
● 无连接状态。
● 分组首部开销小。
TCP 的拥塞控制会导致如因特网电话、视频会议之类的实时应用性能变得很差。由于这些原因,多媒体应用开发人员通常将这些应用运行在 UDP之上而不是 TCP 之上。
当分组丢包率低时,并且为了安全原因,某些机构阻塞 UDP流量,对于流式媒体传输来说,TCP变得越来越有吸引力了。
使用UDP的应用是可能实现可靠数据传输的。这可通过在应用程序自身中建立可靠性机制来完成
UDP报文段结构
长度字段 指示了在 UDP报文段中的字节数(首部加数据)。因为数据字段的长度在一个UDP 段中不同于在另一个段中,故需要一个明确的长度。接收方使用检验和来检查在该报文段中是否出现了差错。
UDP检验和
UDP检验和提供了差错检测功能。这就是说,检验和用于确定当 UDP 报文段从源到达目的地移动时,其中的比特是否发生了改变
发送方的 UDP对报文段中的所有16 比特字的和进行反码运算,求和时遇到的任何溢出都被回卷。得到的结果被放在 UDP 报文段中的检验和字段。
UDP提供差错检测,但无法回复,出现差错的报文段丢弃,给出警告。
可靠数据传输原理
数 据可以通过一条可靠的信道进行传输。借助于可靠信道,传输数据比特就不会受到损坏 (由。变为1,或者相反)或丢失,而且所有数据都是按照其发送顺序进行交付。
实现这种服务抽象是可靠数据传输协议(reliable data transfer protocol)的责任。
构造可靠数据传输协议
经完全可靠信道的可靠数据传输∶rdt1.0
经具有比特差错信道的可靠数据传输∶rd2.0
口述报文协议使用了肯定确认(positive ac-knowledgment)("OK"))与否定确认(negative acknowledgment)("请重复一遍")。这些控制报文使得接收方可以让发送方知道哪些内容被正确接收,哪些内容接收有误并因此需要重复。
基于这样重传机制的可靠数据传输协议称为自动重传请求(Automatic Repeat reQuest,ARQ)协议。 重要的是,ARQ 协议中还需要另外三种协议功能来处理存在比特差错的情况∶
● 差错检测。
● 接收方反馈。
● 重传。
rdt2.0这样的协议被称为停等(stop-and-wait)协议。
当分组到达时,接收方要么回答一个 ACK,要么回答一个NAK,这取决于收到的分组是否受损。
它存在一个致命的缺陷,没有考虑到 ACK或 NAK 分组受损的可能性。
考虑处理受损 ACK和 NAK时的3种可能性∶
解决这个新问题的一个简单方法是在数据分组中添加新字段。让发送方对其数据分组编号。即将发送数据分组的序号(sequence number)放在该字段。于是,接收方只需要检查序号即可确定收到的分组是否一次重传。
协议 rdt2.1使用了从接收方到发送方的肯定确认和否定确认。当接收到失序的分组时,接收方对所接收的分组发送一个肯定确认。如果收到受损的分组,则接收方将发送一个否定确认。如果不发送 NAK,而是对上次正确接收的分组发送一个 ACK,我们也能实现与NAK 一样的效果。发送方接收到对同一个分组的两个 ACK(即接收冗余 ACK (duplicate ACK))后,就知道接收方没有正确接收到跟在被确认两次的分组后面的分组。
经具有比特差错的丢包信道的可靠数据传输∶rdt3.0
现在假定除了比特受损外,底层信道还会丢包,还需增加一种新的协议机制。
实践中采取的方法是发送方明智地选择一个时间值,以判定可能发生了丢包(尽管不能确保)。如果在这个时间内没有收到 ACK,则重传该分组。注意到如果一个分组经历了一个特别大的时延,发送方可能会重传该分组,即使该数据分组及其 ACK 都没有丢失。这就在发送方到接收方的信道中引入了冗余数据分组(duplicate data packet)的可能性。
为了实现基于时间的重传机制,需要一个倒计数定时器(countdown timer),在一个给定的时间量过期后,可中断发送方。因此,发送方需要能做到∶①每次发送一个分组(包括第一次分组和重传分组)时,便启动一个定时器。②响应定时器中断(采取适当的动作)。③终止定时器。
因为分组序号在0和1 之间交替,因此rdt3.0有时被称为比特交替协议(alter- nating-bit protocol)。
流水线可靠数据传输协议
如果我们定义发送方(或信道)的利用率(utilization)为∶发送方实际忙于将发送比特送进信道的那部分时间与发送时间之比,停等协议有着非常低的发送方利用率
发送方只有万分之2.7时间是忙的。发送方在30.008ms 内只能发送 1000字节。有效的吞叶量仅为267kbps。
这种特殊的性能问题的一个简单解决方法是∶不以停等方式运行,允许发送方发送多个分组而无须等待确认。
这种技术被称为流水线(pipelining)。流水线技术对可靠数据传输协议可带来如下影响∶
● 必须增加序号范围,因为每个输送中的分组(不计算重传的)必须有一个唯一的 序号,而且也许有多个在输送中的未确认报文。
● 协议的发送方和接收方两端也许不得不缓存多个分组。发送方最低限度应当能缓 冲那些已发送但没有确认的分组。如下面讨论的那样。接收方或许也需要缓存那些已正确接收的分组。
● 所需序号范围和对缓冲的要求取决于数据传输协议如何处理丢失、损坏及延时过大的分组。解决流水线的差错恢复有两种基本方法是∶回退N步(Co-Back-N,GBN)和选择重传(Selective Repeat,SR)。
回退 N步
在回退 N步(GBN)协议中,允许发送方发送多个分组(当有多个分组可用时)而不需等待确认,但它也受限于在流水线中未确认的分组数不能超过某个最大允许数N。
N 常被称为窗口长度(window size),GBN 协议也常被称为滑动窗口协议(sliding-window protocol)。
GBN 发送方必须响应三种类型的事件∶
● 上层的调用。
● 收到一个ACK。
● 超时事件。
在GBN中,接收方的动作也很简单。如果一个序号为n 的分组被正确接收到,并且按序(即上次交付给上层的数据是序号为 n-1 的分组),则接收方为分组 n发送一个ACK,并将该分组中的数据部分交付到上层。在所有其他情况下,接收方丢弃该分组,并为最近按序接收的分组重新发送 ACK。
在 GBN协议中。接收方丢弃所有失序分组。如果分组 n 丢失,则该分组及分组 n +1最终将在发送方根据 GBN 重传规则而被重传。因此,接收方只需丢弃分组 n+1 即可。这种方法的优点是接收缓存简单,即接收方不需要缓存任何失序分组。
选择重传
选择重传(SR)协议通过让发送方仅重传那些它怀疑在接收方出错(即丢失或受损)的分组而避免了不必要的重传。这种个别的、按需的重传要求接收方逐个地确认正确接收的分组。再次用窗口长度 N来限制流水线中未完成、未被确认的分组数。
SR 发送方的事件与动作
1.从上层收到数据。
2.超时。定时器再次被用来防止丢失分组。
3.收到 ACK。如果收到 ACK,倘若该分组序号在窗口内,则 SR 发送方将那个被确认的分组标记为已接收。
SR接收方的事件与动作
1.序号在【rcv_base,rcv_base +N-1】 内的分组被正确接收。
2.序号在【rcv_base-N,rcv_base-1】 内的分组被正确收到。
3.其他情况。忽略该分组。
可能出现的问题
两次接收的pkt0是不同的,但是无法识别。
面向连接的运输∶TCP
TCP是因特网运输层的面向连接的可靠的运输协议。
TCP连接
TCP 被称为是面向连接的(connection-oriented),这是因为在一个应用进程可以开始向另一个应用进程发送数据之前,这两个进程必须先相互、"握手",即它们必须相互发送某些预备报文段,以建立确保数据传输的参数。
TCP连接也总是点对点(point-to-point)的,即在单个发送方与单个接收方之间的连接。
一旦建立起一条 TCP连接,两个应用进程之间就可以相互发送数据了。
客户进程通过套接字(该进程之门)传递数据流,TCP将这些数据引导到该连接的发送缓存(send buffer)里,发送缓存是发起三次握手期间设置的缓存之一。接下来 TCP就会不时从发送缓存里取出一块数据,并将数据传递到网络层。
TCP 可从缓存中取出并放入报文段中的数据数量受限于最大报文段长度(Maximum Segment Size,MSS)。MSS通常根据最初确定的由本地发送主机发送的最大链路层帧长度(即所谓的最大传输单元(Maximum Transmission Unit,MTU))来设置。
TCP为每块客户数据配上一个TCP首部,从而形成多个TCP报文段(TCP segment)。当TCP在另一端接收到一个报文段后,该报文段的数据就被放入该TCP连接的接收缓存中,该连接的每一端都有各自的发送缓存和接收缓存。
TCP 报文段结构
与UDP 一样,首部包括源端口号和目的端口号,它被用于多路复用/分解来自或送到上层应用的数据。另外,同 UDP 一样,TCP 首部也包括检验和字段(checksum field)。TCP报文段首部还包含下列字段∶
● 32比特的序号字段(sequence number field)和32 比特的确认号字段(acknowl- edgment number field)。
● 16 比特的接收窗口字段(receive window field),该字段用于流量控制。
● 4 比特的首部长度字段(header length field),该字段指示了以32 比特的字为单位 的 TCP首部长度。
● 可选与变长的选项字段(options field),该字段用于发送方与接收方协商最大报文 段长度(MSS)时,或在高速网络环境下用作窗口调节因子时使用。
● 6 比特的标志字段(flag field)。
序号和确认号
TCP报文段首部中两个最重要的字段是序号字段和确认号字段。这两个字段是TCP可靠传输服务的关键部分。
TCP把数据看成一个无结构的、有序的字节流。序号是建立在传送的字节流之上,而不是建立在传送的报文段的序列之上。
确认号要比序号难处理一些。TCP是全双工的,因此主机 A在向主机 B发送数据的同时,也许也接收来自主机 B的数据(都是同一条 TCP 连接的一部分)。从主机 B到达的每个报文段中都有一个序号用于从 B流向 A 的数据。主机A填充进报文段的确认号是主机 A期望从主机 B收到的下一字节的序号。
往返时间的估计与超时
TCP如同rdt 协议一样,它采用超时/重传机制来处理报文段的丢失问题。
估计往返时间
大多数 TCP 的实现仅在某个时刻做一次 SampleRTT测量,而不是为每个发送的报文段测量一个Samp-leRTT。
由于路由器的拥塞和端系统负载的变化,这些报文段的 SampleRTT 值会随之波动。
一旦获得一个新 SampleRTT时,TCP 就会根据下列公式来更新
Esti-matedRT: EstimatedRTT'=(1-α)· EstimatedRTT +α·SampleRTT
α推荐值是α=0.125(即1/8),这时上面的公式变为∶
EstimatedRTT=0.875· EstimatedRTT+0.125·SampleRTT
设置和管理重传超时间隔
在 TCP 的确定重传超时间隔的方法中,所有这些因素都考虑到了∶
TimeoutInterval = EstimatedRT +4· DevRT
SampleRTT一般会偏离 EstimatedRTT的程度∶
DevRTT=(1-β)·DevRTT +β·|SampleRTT-EstimatedRTT
β的推荐值为0.25。
可靠数据传输
TCP在IP不可靠的尽力而为服务之上创建了一种可靠数据传输服务(reliable data transfer service)。TCP 的可靠数据传输服务确保一个进程从其接收缓存中读出的数据流是无损坏、无间隙、非冗余和按序的数据流;即该字节流与连接的另一方端系统发送出的字节流是完全相同。
快速重传
超时触发重传存在的问题之一是超时周期可能相对较长。 当一个报文段丢失时。这种长超时周期迫使发送方延迟重传丢失的分组,因而增加了端到端时延。因为 TCP不使用否定确认,所以接收方不能向发送方发回一个显式的否定确认。相反,它只是对已经接收到的最后一个按序字节数据进行重复确认(即产生一个冗余 ACK)即可。
因为发送方经常一个接一个地发送大量的报文段,如果一个报文段丢失,就很可能引起许多一个接一个的冗余 ACK。如果 TCP发送方接收到对相同数据的3个冗余 ACK,TCP就执行快速重传(fast retransmit),即在该报文段的定时器过期之前重传丢失的报文段。
流量控制
TCP为它的应用程序提供了流量控制服务(flow-control service)以消除发送方使接收方缓存溢出的可能性。
TCP 发送方也可能因为 IP 网络的拥塞而被遏制;这种形式的发送方的控制被称为拥塞控制(congestion control)
TCP通过让发送方维护一个称为接收窗口(receive window)的变量来提供流量控制。
TCP连接管理
第一步∶客户端的TCP首先向服务器端的TCP发送一个特殊的TCP报文段。该报 文段中不包含应用层数据。但是在报文段的首部(参见图3-29)中的一个标志位(即 SYN比特)被置为1。另外,客户会随机地选择一个初始序号(client_isn),并将此编号放置于该起始的 TCP SYN 报文段的序号字段中。该报文段会被封装在一个IP 数据报中,并发送给服务器。
第二步∶ 一旦包含TCP SYN 报文段的IP数据报到达服务器主机(假定它的确到达 了!),服务器会从该数据报中提取出 TCP SYN报文段,为该TCP连接分配TCP缓存和变量,并向该客户 TCP发送允许连接的报文段。这个允许连接的报文段也不包含应用层数据。但是,在报文段的首部却包含3个重要的信息。首先,SYN 比特被置为1。其次,该 TCP报文段首部的确认号字段被置为 client_isn +1。最后,服务器选择自己的初始序号(server_isn),并将其放置到 TCP报文段首部的序号字段中。
第三步∶在收到SYNACK 报文段后,客户也要给该连接分配缓存和变量。客户主 机则向服务器发送另外一个报文段;这最后一个报文段对服务器的允许连接的报文段进行了确认。因为连接已经建立了,所以该 SYN 比特被置为0。该三次握手的第三个阶段可以在报文段负载中携带客户到服务器的数据。
一但完成这 3个步骤,客户和服务器主机就可以相互发送包括数据的报文段了。在以后每一个报文段中,SYN 比特都将被置为0。这种连接创建过程通常被称为3 次握手(three-way handshake)。
TCP拥塞控制
拥塞窗口表示为 cwnd,它对一个TCP发送方能向网络中发送流量的速率进行了限制。特别是,在一个发送方中未被确认的数据量不会超过cwnd与rwnd 中的最小值,即
LastByteSent -LastByteAcked≤min { cwnd, rwnd}
TCP使用下列指导性原则
● 一个丢失的报文段表意味着拥塞,因此当丢失报文段时应当降低 TCP发送方的 速率。
● 一个确认报文段指示该网络正在向接收方交付发送方的报文段,因此,当对先前 未确认报文段的确认到达时,能够增加发送方的速率。
● 带宽探测。
慢启动
当一条TCP连接开始时,cwnd 的值通常初始置为一个MSS 的较小值 ,这就使得初始发送速率大约为 MSS/RTT。因此,在慢启动(slow-start)状态,cwnd 的值以1个 MSS开始并且每当传输的报文段首次被确认就增加 1个 MSS。
这一过程每过一个 RTT,发送速率就翻番。因此,TCP 发送速率起始慢,但在慢启动阶段以指数增长。
结束这种指数增长
首先,如果存在一个由超时指示的丢包事件(即拥塞),TCP发送方将 cwnd 设置为1并重新开始慢启动过程。它还将第二个状态变量的值ssthresh("慢启动阈值"的速记)设置为 cwnd/2,即当检测到拥塞时将ssthresh 置为拥塞窗口值的一半。
慢启动结束的第二种方式是直接与ssthresh的值相关联。当cwnd 的值等于 ssthresh 时,结束慢启动并且 TCP转移到拥塞避免模式。当进入拥塞避免模式时,TCP 更为谨慎地增加 cwnd。
最后一种结束慢启动的方式是,如果检测到3个冗余 ACK,这时 TCP执行一种快速重传并进入快速恢复状态。
拥塞避免
一旦进入拥塞避免状态,cwnd 的值大约是上次遇到拥塞时的值的一半。TCP无法每过一个 RTT 再将 cwnd 的值翻番,而是采用了一种较为保守的方法,每个RTT只将 cwnd 的值增加一个 MSS。
结束拥塞避免的线性增长
当出现超时时,TCP 的拥塞避免算法行为相同。与慢启动的情况一样,cwnd 的值被设置为1个MSS。TCP对这种丢包事件的行为,相比于超时指示的丢包,应当不那么剧烈∶TCP将 cwnd 的值减半,并且当收到3个冗余的 ACK,将ssthresh的值记录为 cwnd 的值的一半。
接下来进入快速恢复状态。
快速恢复
对收到的每个冗余的ACK,cwnd 的值增加一个MSS。当对丢失报文段的一个ACK 到达时,TCP在降低cwnd后进入拥塞避免状态。如果出现超时事件,快速恢复在执行如同在慢启动和拥塞避免中相同的动作后,迁移到慢启动状态∶当丢包事件出现时,cwnd 的值被设置为1个MSS,并且 ssthresh的值设置为 cwnd值的一半。
TCP CUBIC
增加cwnd速度变成三次方。
当丢包发生时,将此时的速率记录
增加TCP的发送速率,直到某个路由器的输出(瓶颈链路)发生数据包丢失(瓶颈链路)
cwnd减半后,上升速度更快,接近上次丢包时的速率更慢
K:TCP窗口大小将达到Wmax的时间点,K本身是可调的。
K变大,增加更多。K变小,增加更少。
增加TCP的发送速率,直到某个路由器的输出(瓶颈链路)发生数据包丢失