在协议栈中,运输层刚好位于网络层之上。网络层提供了主机之间的逻辑通信,而运输层为运行在不同主机上的进程之间提供了逻辑通信。
运输层协议能够提供的服务常常受制于底层网络层协议的服务模型。如果网络层协议无法为主机之间发送的运输层报文段提供时延或带宽保证的话,运输层协议也就无法为进程之间发送的应用程序报文提供时延或带宽保证。
底层网络协议不能在网络层提供相应的服务,运输层协议也能提供某些服务。
运输层协议是在端系统中实现的。因特网的运输层有两种协议, 分别是TCP和UDP,每种协议都能为调用的应用程序提供一组不同的运输层服务
UDP和TCP最基本的责任
将两个端系统间 IP 的交付服务扩展为运行在端系统上的两个进程之间的交付服务。将主机间交付扩展到进程间交付被称为运输层的多路复用与多路分解。UDP和TCP 还可以通过在其报文段首部中包括差错检查字段而提供完整性检查。进程到进程的数据交付和差错检查是两种最低限度的运输层服务、也是 UDP 所能提供的仅有的两种服务。
TCP的附加服务
多路分解:将运输层报文段中的数据交付到正确的套接字的工作称为多路分解。
多路复用:在源主机从不同套接字中收集数据块,并为每个数据块封装上首部信息从而生成报文段,然后将报文段传递到网络层,所有这些工作称为多路复用。
1.无连接的多路复用与多路分解
一个端系统可能运行多个进程,每个进程都具有其自己的 UDP 套接字,UDP套接字由一个二元组标识,该二元组包含一个目的IP地址和目的端口号。UDP 报文段从网络到达时,主机通过检查该报文段中的目的端口号,将每个报文段定向分解到相应的套接字。
2.面向连接的多路复用与多路分解
TCP 套接字 UDP 套接字之间的一个细微差别是,TCP 套接字是由一个四元组(源 IP 地址, 源端口号,目的 IP 地址,目的端口号)来标识的。因此当一个 TCP 报文段从网络到达一台主机时, 该主机使用全部4个值来将报文段定向分解到相应的套接字。特别与 UDP 不同的是,两个具有不同源 IP 地址或源端口号的到达 TCP 文段将被定向到两个不同的套接字 ,除非 TCP 报文段携带了初始创建连接的请求(也就是三次握手中的请求)。
3.Web服务器与TCP
在Web服务器端,有二个套接字,分别是欢迎套接字和连接套接字。连接套接字与进程之间并非总是有着一一对应的关系。事实上,当今高性能服务器通常只使用一个进程,但是为每个新的客户连接创建一个具有新连接套接字的新线程。对于这样一台服务器,在任意给定的时间内都可能有(具有不同标识的)许多连接套接字连接到相同的进程。
报文:应用层的分组
报文段:TCP和UDP的分组
数据报:网络层的分组
UDP是一种无连接的,提供不可靠服务的运输层协议
流行的因特网应用及其下面的运输协议
UDP提供的服务
UDP报文段结构
如上图所示,UDP报文段的首部有四个字段,每个字段由2个字节组成,其中
长度字段:指示了在UDP报文段中首部加数据的字节数
检验和字段:接收方使用检验和来检查UDP报文段从源到目的地移动时,其中的比特是否发生了变化。例如,由于链路中的噪声干扰或者存储在路由器中时引入问题。
虽然UDP提供差错检测,但它对差错恢复无能为力。UDP的某种实现只是丢弃受损的报文段。
用到了再更新
TCP 通过三次握手建立连接,以建立确保数据传输的参数,连接的双方都将初始化与 TCP 连接相关的许多 TCP 状态变量。该连接是一条逻辑连接,其共同状态仅保留在二个通信端系统的TCP程序中。
TCP连接的组成包括:一台主机上的缓存、变量和与进程连接的套接字,以及另一台主机上的另 一组缓存、变量和与进程连接的套接字。
MTU:本地发送主机发送的最大链路层帧长度。以太网和 PPP 链路层协议都具有500 字节的 MTU,MSS 的典型值为1460 字节。路径 MTU 是指能在从源到目的地的所有链路上发送的最大链路层,已经提出了多种发现路径 MTU 的方法,并基于路径 MTU 值设 MSS。
MSS:TCP 可从缓存中取出并放入报文段中的数据数量受限于最大报文段长度 (MSS),MSS 通常根据 MTU 来设置。设置该 MSS 要保证一个 TCP 报文段(当封装在一个 IP 数据报中)加上 TCP/ IP 首部长度将适合单个链路层帧。
三次握手建立TCP连接
第一步:客户端的TCP向服务器端的TCP发送一个不包含应用层数据的特殊TCP报文段,在该报文段的首部中的一个标志位SYN被置为1。因此,这个特殊报文段被称为SYN报文段。另外,客户端TCP会随机选择一个初始序号放置于SYN报文段的序号字段中。最后,该SYN报文段会被封装在一个IP数据报中发送给服务器。
第二步:一旦包含SYN报文段的IP数据报到达服务器主机,服务器会从该数据报中提取出SYN报文段,为该TCP连接分配TCP缓存和变量,并向客户端TCP发送允许连接的报文段,这个允许连接的报文段也不包含应用层数据。但是,在该报文段的首部。首先SYN比特被置为1。其次,确认号字段被置为client_isn+1。最后,服务器选择自己的初始序号,并将其放置到序号字段中。该允许连接的报文段被称为SYNACK报文段。
第三步:客户端TCP收到SYNACK报文段后,客户也要给该连接分配缓存和变量。客户主机则向服务器发送另外一个报文段,这最后一个报文段对服务器的允许连接的报文段进行了确认。因为连接已经建立了,所以该SYN标志位被置为0。第三次握手可以在报文段中携带应用层的数据。
四次挥手断开连接
第一步:客户应用进程发出一个关闭连接命令。这会引起客户TCP向服务器进程发送一个首部FIN标志位被置为1的特殊TCP报文段.
第二步:服务器接收到该报文段后,就向发送方回送一个确认报文段。
第三步:服务器再次发送自己的终止报文段,其首部FIN标志位被置为1.
第四步:最后,客户对这个服务器的终止报文段进行确认。
当一台主机接收到一个 TCP 报文段,其端口号或源 IP 地址与该主机上进行中的套接字都不匹配的情况。例如 假如一台主机接收了具有目的端口 80 的一个 TCP SYN 分组,但该主机在端口 80 不接受连接(即它不在端口 80 上运行 Web 服务器)。则该主机将向源发送一个特殊重置报文段。TCP 报文段将 RST 标志位置为1。因此,当主机发送一个重置报文段时,它告诉该源“我没有那个报文段的套接字 请不要再发送该报文段了"。
当一台主机接收 UDP 分组,它的目的端口与进行中的 UDP 套接字不匹配,该主机发送一 个特殊的 ICMP 数据报,这将在后面讨论。
源端口号和目的端口号:含义从名字就能看出来。
序号和确认号:这二个字段被 TCP 发送方和接收方用来实现可靠数据传输服务,每个字段都是32比特。
接收窗口:该字段用于流量控制,大小为16比特。
首部长度:该字段指示了以 32 比特的字为单位的 TCP 首部长度,大小为4比特。
标志字段:
实践中,PSH、URG和紧急数据指针并没有使用。
检验和:同上边的UDP。
选项:该字段用于发送方与接收方协商最大报文段长度时,或在高速网络环境下用作窗口调节因子时使用。在实践中, PSH、URG 和紧急数据指针并没有使用。
数据:存放着多路复用/多路分解来自或送到上层应用的数据。
1.估计往返时间
大多 TCP 的实现仅在某个时刻做一次 SampleRTT 测量,而不是为每个发送的报文段测量一个 SampleRTT 这就是说,在任意时刻,仅为一个已发送的但目前尚未被确认的报文段估计 SampleRTT,从而产生一个接近每个 RTT 的新 SampleRTT。 另外,TCP 决不为已被重传的报 文段计算 SampleRTT;它仅为传输一次的报文段测量 SampleRTT。
由于路由器的拥塞和端系统负载的变化,这些报文段的 SampleRTT 值会随之波动。由于这种波动,任何给定的 SampleRTT 值也许都是非典型的。因此,为了估计一个典型的 RTT,自然要采取某种对 SampleRTT 取平均的办法。TCP 维持一个 SampleRTT 均值,称为 EstimatedRTT。一旦获得一个新 SampleRTT 时,TCP 就会根据下列公式来更新 EstimatedRTT:
其中,在 [RFC 6298] 中给出的 α 推荐值是 a= 0. 125。
TCP连接上SampleRTT 值与 EstimatedRTT值的一个典型对比如下图所示:
除了估算 RTT 外,测量RTT的变化也是有价值的。 [RFC 6298] 定义了 RTT偏差DevRTT,用于估算 SampleRTT 一般会偏离 EstimatedRTT 的程度:
2.设置和管理重传超时间隔
假设巳经给出了 EstimatedRTT 值和 DevRTT 值,,超时间隔应该大于等于 EstimatedRTT, 否则,将造成不必要的重传。TCP 在确定重传超时间隔时,采用下述公式确定:
推荐的初始 TimeoutInterval 值为 [RFC 6298] 。同时,当出现超时后,Timeoutlnterval 值将加倍,以免即将被确认的后继报文段过早出现超时。然而,只要收到报文段并更 EstimatedRTT 就使用上述公式再次计算 TimeoutInterval。
1.TCP保证可靠数据传输的方法
TCP主要提供了检验和、序号/确认号、超时重传、最大报文段长度、流量控制等方法实现了可靠数据传输。
检验和
通过检验和的方式,接收端可以检测出来数据是否有差错和异常,假如有差错就会直接丢失该TCP报文段。
序号/确认号
序号:TCP传输时将每个字节的数据都进行了编号,这就是序号,一个报文段的序号字段因此是该报文段首字节的字节流编号。
确认号:主机 A 填充进报文段的确认号是主机 A 期望从主机 B 收到的下一字节的序号。
在上图中,通过序号和确认号,只要发送端有一个报文段传输,接收端没有通过确认号回应(ACK用来保证确认号是有效的),都会重发。或者接收端的响应报文段在网络中丢失了,导致发送端没有收到,也会重发数据。这就可以保证数据的完整性。
超时重传
在进行TCP传输时,TCP每发送一个报文段,都会在一个超时间隔内等待接收方发送回一个ACK确认报文段,如果在这个超时间隔内没有收到ACK确认报文段就会触发超时重传,TCP发送端就会重新发送此报文段。
这个超时间隔是按照3.5.3节的方法动态计算的
最大报文段长度:MSS
在建立TCP的时候,双方约定一个最大报文段长度(MSS)进行发送,重传的时候也是根据这个长度进行重传。
流量控制
一般来说,我们总希望数据传输的更快一些。但如果发送方把数据发得过快,接收方就可能来不及接收,这就会造成数据的丢失。流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收。
利用滑动窗口机制可以很方便地在TCP连接上实现发送方流量控制。通过接收方的确认报文中的窗口字段,发送方能够准确地控制发送字节数。
TCP通过让发送方维护一个称为接收窗口的变量来提供流量控制。通俗的说,接收窗口用于给发送方一个指示:该接收方还有多少可用的缓存空间。因为TCP是全双工通信,在连接两端的发送方都各自维护一个接收窗口rwnd,rwnd是动态变化的,下图对变量rwnd进行了图示。
接收窗口rwnd由以下公式得到:
rwnd = RcvBuffer - [LastByteRcvd - LastByteRead]
其中,
LastByteRcvd:接收方上的应用程序从缓存读出的数据流的最后一个字节的编号。
LastByteRead:从网络中到达的并且已放入接收方的接收缓存中的数据流的最后一个字节的编号。
LastByteRcvd - LastByteRead <= RcvBuffer
接收方通过把当前的rwnd值放入它发给发送方的报文段接收窗口字段中,通知发送方它在该连接的缓存中还有多少可用空间。开始时,接收方设定rwnd = RcvBuffer。
发送方轮流跟踪两个变量, LastByteSent和LastByteAcked,这两个变量的意义很明显,注意到这两个变量之间的差 LastByteSent - LastByteAcked,就是发送方发送到连接中但未被确认的数据量, 通过将未确认的数据量控制在值 rwnd 以内,就可以保证发送方不会使接收方的接收缓存溢出。 因此,发送方在该连接的整个生命周期须保证
LastByteSent - LastByteAcked <= rwnd
滑动窗口机制:缓存中会有一个窗口,这个窗口中全部都是发送方已发送但未收到响应ACK的报文段,当窗口中最早的那个已发送但未收到响应收到了响应报文段之后,滑动窗口会右滑。
2.超时间隔加倍
TCP重传具有最小序号的还未被确认的报文段时,如果TCP下次重传的还是此分组,那么会将此分组的超时定时器的时间间隔增加为原先的二倍。
3.快速重传
TCP发送方会在超时事件发生之前通过注意是否有3个冗余的ACK来决定是否重新发送冗余ACK所对应的报文段及之后的报文段。
如果TCP发送方接收到对相同数据的3个冗余ACK,它会把这当做一种暗示,说明跟在这个已被确认过3次的报文段之后的报文段已经丢失,TCP就执行快速重传。
超时间隔加倍和快速重传只是大多数TCP实现中所做的一些修改,并非所有TCP均有此机制
用到再更新
什么是网络拥塞
计算机网络中的带宽、交换结点中的缓存和处理机等,都是网络的资源。在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就会变坏。这种情况就叫做网络拥塞。
什么是拥塞控制
拥塞控制就是防止过多的数据注入网络中,这样可以使网络中的路由器或链路不致过载。拥塞控制是一个全局性的过程,和流量控制不同,流量控制指点对点通信量的控制。
假定:
1.数据是单方向传送,而另一个方向只传送确认
2.为了关注拥塞控制以和流量控制形成对比,假设接收方总是有足够大的缓存空间。
3.以TCP报文段的个数为讨论问题的单位,而不是以字节为单位
在上面这三个假设的限制下,会有以下的结论
发送方维护一个称为拥塞窗口cwnd的状态变量,其值取决于网络的拥塞程度,并且动态变化。特别是,在一个发送方中未被确认的数据量不会超过cwnd与rwnd的最小值。因为在上面假设了接收方的接收缓存足够大,所以可以忽略接收窗口rwnd的限制,因此在发送方中未被确认的报文段仅受限于cwnd。
发送方将拥塞窗口作为发送窗口,即swnd = cwnd
维护一个慢启动阈值ssthresh状态变量:
慢启动算法和拥塞避免算法都是TCP的拥塞控制算法,接下来对这几种算法进行介绍
1.慢启动
在tcp双方建立逻辑连接关系时, 拥塞窗口cwnd的值被设置为1,还需设置慢启动阈值ssthresh,因此发送方当前只能发送一个数据报文段(拥塞窗口cwnd的值是几,就能发送几个数据报文段),接收方收到该数据报文段后,给发送方回复一个确认报文段,发送方收到该确认报文后,将拥塞窗口的值变为2,并继续这样下去。因此,TCP发送速率起始慢,但在慢启动阶段以指数增长。
2.拥塞避免算法
当cwnd > ssthresh时,进入拥塞避免阶段,此时的拥塞窗口缓慢增加,每经过一个往返时间RTT,就把拥塞窗口加1,而不是成倍增加。因此在拥塞避免阶段就有“加法增大”的特点,拥塞窗口按线性规律缓慢增长。
如下图:
红色这一部分就是拥塞避免算法,每次拥塞窗口仅仅增加一个大小,当增加到一定大小时,就碰到了网络超时,即出现网络拥塞。
出现阻塞后调整
当出现阻塞之后,会调整慢启动阈值ssthresh以及拥塞窗口的值:
新的慢开始门限的值:ssthresh=cwnd/2。
如上图所示,此时cwnd已经增长到了24大小,所以此时ssthresh=24/2=12。拥塞窗口则再次变为1
调整后的运行过程如下图所示:
如上图所示,当在24出现阻塞后,将cwnd变为了1,将ssthresh变为了12
然后在12之前依旧是进行慢开始算法,在12之后进行拥塞避免算法,直到16发生了3个ACK情况(这个后面讲)又一次出现了网络阻塞。
从上面可知,在16的时候又一次出现了拥塞,而这次拥塞出现的原因就是这3个ACK。这个也就是快重传。
快重传:当发生报文段丢失时,为了让发送方尽早知道发生了个别报文段的丢失,因此立即发送确认,怎样让发送方知道是哪个报文段丢失的方法就是连读发送三个确认。
如下图所示:
当丢失某个数据包时,连续发送三个确认,则发送方就知道某个包丢失了,然后立即启动快重传。
快恢复:发送方知道现在只是丢失了个别的报文段。于是不执行慢开始,而是执行快恢复算法。
新的慢开始门限的值:ssthresh=cwnd/2。
如上图所示,此时新的cwnd已经增长到了16大小,所以此时ssthresh=16/2=8。拥塞窗口不是变为1,而是和门限值一样,此时cwnd=ssthresh=8,然后开始执行拥塞避免算法
如下图所示:
如上图是怎样判断出现了丢包现象,以及出现丢包情况下进行快恢复的流程。
注意:
- 无论是在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞,就把慢启动阈值设置为出现拥塞时的发送窗口大小的一半。然后把拥塞窗口设置为1,执行慢启动算法
- 快速恢复是TCP推荐的而非必须的构件。一种称为 TC Tahoe 的TCP 早期版本,不管是发生超时指示的丢包事件,还是发生3个冗余 ACK 指示的丢包事件,都无条件地将其拥塞窗口减至 1个MSS,并进入慢启动阶段。TCP 的较新版本 TCP Reno , 则综合了快速恢复。
如果有K条TCP连接,都经过一段瓶颈链路,如果每条连接都得到相同份额的链路带宽,则认为该拥塞控制机制是公平的。
在理想化情形下,所有连接都具有相同的RTT、MSS等,所以是公平的。但在实践中,这些条件通常是得不到满足的,客户-服务器应用因此获得非常不平等的链路带宽份额。
1.公平性和UDP
因为UDP没有实现拥塞控制,所以UDP不与TCP连接合作,当出现拥塞时,UDP流量会不断压制TCP流量。
2.公平性和并行TCP连接
Web浏览器通常使用多个并行的TCP连接来传送一个Web页中的多个对象。这就导致一个应用使用多条并行连接时,它占用一条拥塞链路中较大比例的带宽。
我们知道,TCP 发送方不会收到来自网络层的明确拥塞指示,而是通过观察分组丢失来推断拥塞。最近,对于 IP和TCP 的扩展方案 RFC 3168 已经提出并已经实现和部署,该方案允许网络明确向 TCP 发送方和接收方发出拥塞信号。这种形式的网络辅助拥塞控制称为明确拥塞通告。
如下图所示,涉及了 TCP 和 IP 协议。
在网络层, IP 数据报首部的服务类型字段中的两个比特(总的说来有四种可能的值)被用于 ECN 路由器所使用的 ECN 比特设置指示该路由器正在历经拥塞。该拥塞指示则由被标记的 IP 数据报所携带,送给目的主机,再由目的主机通知发送主机,如上所示,RFC 3168 没有提供路由器拥塞时的定义;该判断是由路由器厂商所做的配置选择,并且由网络操作员决定。然而, RFC 3168 推荐仅当拥塞持续不断存在时才设置 ECN 比特。发送主机所使用的另一种 ECN 比特设置通知路由器发送方和接收方是 ECN 使能的,因此能够对于 ECN 指示的网络拥塞采取行动。
如上图所示,当接收主机中的 TCP 通过一个接收到的数据报收到了一个 ECN 拥塞指示时,接收主机中的 TCP 通过在接收方到发送方的 TCP ACK 报文段中设置 ECE (明确拥塞通告回显)比特,通知发送主机中的 TCP 收到拥塞指示。接下来,TCP 发送方通过减半拥塞窗口对一个具有 ECE 拥塞指示的 ACK 做出反应,就像它对丢失报文段使用快速重传做出反应一样,并且在下一个传输的 TCP 发送方到接收方的报文段首部中对 CWR (拥塞窗口缩减)比特进行设置。