1. 运输层协议概览
1.1进程之间的通信
通信的真正端点并不是主机而是主机中的进程。
运输层有一个很重要的功能复用和分用。
- 复用:是指在发送方不同的应用进程都可以使用同一个运输层协议传送数据(当然需要加上适当的首部);
- 分用:是指接收方的运输层在剥去报文的首部后能够把这些数据正确交付目的应用进程。
网络层为主机之间提供逻辑通信,而运输层为应用进程之间提供端到端的逻辑通信。
运输层还要对收到的报文进行差错检测。在网络层,IP数据报首部中的检验和字段,只检验首部是否出现差错而不检查数据部分。
我们还应指出,运输层向高层用户屏蔽了下面网络核心的细节(如网络拓扑、所采用的路由选择协议等)。
当运输层采用面向连接的TCP协议时,尽管下面的网络是不可靠的,但这种逻辑通信信道就相当于一条全双工的可靠信道。但当运输层采用无连接的UDP协议时,这种逻辑通信信道仍然是一条不可靠信道
1.2 运输层的两个协议
用户数据报协议UDP
UDP在传送数据之前不需要先建立连接。远地主机的运输层在收到UDP报文后,不需要给出任何确认。虽然UDP不提供可靠交付,但在某些情况下UDP却是一种最有效的工作方式。
传输控制协议TCP
TCP则提供面向连接的服务。在传送数据之前必须先建立连接,数据传送结束后要释放连接。TCP不提供广播或多播服务。由于TCP要提供可靠的、面向连接的运输服务,因此不可避免地增加了许多的开销。
1.3 运输层的端口
运输层使用端口,这种在协议栈层间的抽象协议端口是软件端口,是应用层各种协议进程与运输实体进行层间交互的一种地址
- 服务器使用端口号:一类叫做熟知端口号或系统端口号[0-1023];来一种叫做登记端口号[1024-49152]
- 客户端使用端口号:这类端口号是动态选择的,又叫做短暂端口号[49152-65535]
2. UDP用户数据报协议
2.1 UDP的特点
- UDP是无连接的
- UDP使用尽最大努力交付
- UDP是面向报文的,不会对应用层的报文进行拆分或合并,直接加上首部交付给ip层
- UDP没有拥塞控制,对实时应用十分友好
- UDP支持一对一、一对多、多对一、多对多的通信
- UDP首部开销小
2.2 UDP的首部格式
- 源端口:源端口号。在需要对方回信时选用。不需要时可用全0
- 目的端口:目的端口号。这在终点交付报文时必须使用。
- 长度:UDP用户数据报的长度,其最小值是8(仅有首部)
- 检验和:检测UDP用户数据报在传输中是否有错。有错就丢弃。
如果端口不正确,ICMP就会发送端口不可达的差错报文
请注意,虽然在UDP之间的通信要用到其端口号,但由于UDP的通信是无连接的,因此不需要使用套接字
伪首部只是用于计算校验和,真正传输过程中不存在
3 TCP 传输控制协议
3.1 TCP的主要特点
- 面向连接的运输层协议
- 只能由两个端口
- 提供可靠交付服务
- 提供全双工通信
- 面向字节流:将数据看作无结构的字节流进行传送
3.2TCP的连接
TCP连接的端点叫做套接字或者插口
TCP连接::={socket1,socket2}={(IP1:port1),(IP2:port2)}
3.3 TCP报文段的首部格式
下面只介绍常见的字段
- 序号:本报文段所发送数据的第一个字节的序号,起始序号在建立连接时候确定,如果本报文携带数据为100字节,下一个数据报的序号+100
- 确认号:期望收到对方下一个报文段的第一个数据字节的序号,确认号为N,则表示N-1的数据都正常接收了
- 数据偏移:加上可选部分首部的总长度,单位是4字节,总长度最长为60字节
- URG紧急:UGR=1时,报文段有紧急数据应尽快传送
- ACK确认:ACK=1时,确认号字段才生效,规定连接后的ACK均为1
- PSH推送:PSH=1时,尽快的交付应用进程,无需等到缓存填满
- RST复位:RST=1时,表示出现严重错误,必须释放连接后重新建立
- SYN同步:SYN=1 && ACK=0时,表示连接请求报文
- FIN终止:FIN=1时,表示请求释放报文
- 窗口:接收方返回自己的窗口值,发送方的窗口不能比这个大,窗口值是动态变化的
- 紧急指针:URG=1时,紧急指针才有效,指出本报文中紧急数据的字节数,之后的时普通报文,即使窗口为0也可以发送紧急报文
3.TCP连接的建立
TCP连接的建立采用客户服务器(C-S)方式。主动发起连接建立的应用进程叫做客户,而被动等待连接建立的应用进程叫做服务器
3.1 三次握手——TCP连接的建立
- 服务器B创建传输控制块TCB,B处于监听状态,等待客户的连接请求
- A创建传输控制块TCB,向B发送请求连接报文段,同步位SYN=1,初始序号seq=x,ACK=0。规定SYN=1时不能携带数据,但要消耗一个序号。
- B收到请求后,向A发送确认报文,SYN=1,ACK=1,确认号ack=x+1,同时设置一个自己的序号seq=y。规定此时也不能携带数据,但同样消耗掉一个序号。
- A收到B的确认之后,再向B发送确认,ACK=1,seq=x+1,ack=y+1。规定此时可以携带数据,但如果不携带数据那就不消耗序号,那么下一次报文段序号seq=x+1
A为什么要进行一次确认?
这主要是为了防止已失效的连接请求报文段突然又传送到了B,因而产生错误。
现假定出现一种异常情况,即A发出的第一个连接请求报文段并没有丢失,而是在某些网络结点长时间滞留了,以致延误到连接释放以后的某个时间才到达B。本来这是一个早已失效的报文段。但B收到此失效的连接请求报文段后,就误认为是A又发出一次新的连接请求。于是就向A发出确认报文段同意建立连接。假定不采用报文握手,那么只要B发出确认,新的连接就建立了。
由于现在A并没有发出建立连接的请求,因此不会理睬B的确认,也不会向B发送数据。但B却以为新的运输连接已经建立了,并一直等待A发来数据。B的许多资源就这样白白浪费了。
3.2 四次挥手——TCP的连接释放
- A发送连接释放报文,FIN=1,序号是上一次最后的序号+1,seq=u。规定,FIN报文不携带数据,但消耗一个数据号。
- B收到后发送确认报文,确认号ack=u+1,序号也是上一次最后的序号+1,seq=v,此时A->B方向的连接已经释放了,但B->A的连接还在,可能B还会发送一定时间的数据。
- A收到确认后,进入FIN-WAIT-2状态,等待B发送释放报文段
- 等到B再没有需要发送的数据时,发送释放报文段,FIN=1,ACK=1,假设此时seq=w(半关闭状态时又发送一部分数据),确认号依旧不变ack=u+1
- A收到请求后发送确认报文,ACK=1,ack=w+1,seq=u+1,然后进入时间等待计时器,设置两倍最长报文段寿命时间MSL后,再真正关闭连接。
为什么要等2MSL时间
- 为了保证B的收到最后一个ACK报文。如果没收到B会超时重传FIN+ACK报文,A在2MSL时间内能够收到,并重新发送确认,重新计时,保证AB都正常close
- 防止出现失效的连接请求报文。A发送完最后一个ACK的2MSL后,A产生的所有报文都从网络中消失了,这样新的连接就不会出现旧的连接请求报文段
注:第三次握手防止的短时间发出两次连接请求(第一次没有连接成功),第四次挥手是防止本次正常连接的报文影响之后的连接 以及 B可以正常关闭
保活计时器
除了等待计时器外,TCP还有一个保活计时器。服务器每收到一次客户的数据,就重新设置保活计时器,时间的设置通常是两小时。若两小时没有收到客户的数据,服务器就发送一个探测报文段,以后则每隔75秒钟发送一次。若一连发送10个探测报文段后仍无客户的响应,服务器就认为客户端出了故障,接着就关闭这个连接。
4.TCP的可靠传输
首先介绍一些简单的协议保证TCP能在IP层的通信尽量变得可靠
4.1 停止等待协议
停止等待就是没法送一个分组就停止发送,等待确认后再发送下一组
4.1.1 出现差错
A超过了一段时间没有收到确认,就认为刚才发送的分组丢失了,这时重传前面发送过的分组,这叫做超时重传。每个分组传送完后都设置一个超时计数器,收到确认方可取消。
- 注意事项
- 必须暂时保留已发送分组的副本,直到收到确认号时再清除暂时保留的分组副本。
- 分组和确认分组都要编号
- 重传时间应该比数据在分组传输的平均往返时间还要长一点
4.1.2 确认丢失和确认迟到
- 确认丢失:A没有收到确认
- A进行超时重传
- B丢弃这个重复分组M1
- B向A发送确认
- 确认迟到:A收到重复的确认
- A进行超时重传M1
- B丢弃重复的M1
- A丢弃重复的ack
上述的可靠传输协议称为自动重传ARQ
4.1.3 通道利用率
停止等待协议的通道利用率太低,使用流水线传输会大大提高信道利用率
4.2 连续ARQ协议
这里先给出连续ARQ协议的最基本概念
接收方一般都是采用累积确认的方式。这就是说,接收方不必对收到的分组逐个发送确认,而是在收到几个分组后,对按序到达的最后一个分组发送确认,这就表示:到这个分组为止的所有分组都已正确收到了。
4.3 以字节为单位的滑动窗口
TCP的滑动窗口是以字节为单位的。为了便于说明滑动窗口的工作原理。现假定A收到了B发来的确认报文段,其中窗口是20字节,而确认号是31(这表明B期望收到的下一个序号是31,而序号30为止的数据已经收到了)
我们先讨论发送方A的发送窗口。发送窗口表示:在没有收到B的确认的情况下,A可以连续把窗口内的数据都发送出去。凡是已经发送过的数据,在未收到确认之前都必须暂时保留,以便在超时重传时使用。
A发送了11个字节的数据A收到新的确认号,发送窗口向前滑动
发送窗口内的序号都属于已发送但未被确认
5.TCP的流量控制
流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收。
利用可变窗口进行流量控制举例
为了解决窗口为0时因报文丢失发生死锁的问题,TCP为每一个连接设有一个持续计时器。只要TCP连接的一方收到对方的零窗口通知,就启动持续计时器。若持续计时器设置的时间到期,就发送一个零窗口探测报文段,而对方就在确认这个探测报文段时给出了现在的窗口值。如果窗口仍然是零,那么收到这个报文段的一方就重新设置持续计时器。如果窗口不是零,那么死锁的僵局就可以打破了。
6.TCP的拥塞控制
网络中某一资源的需求超过了该资源所能提供的可用部分,即为发生拥塞
拥塞控制与流量控制的关系密切,它们之间也存在着一些差别。所谓拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。拥塞控制所要做的都有一个前提,就是网络能够承受现有的网络负荷。
从可看出,随着提供的负载的增大,网络吞吐量的增长速率逐渐减小。也就是说,在网络吞吐量还未达到饱和时,就已经有一部分的输入分组被丢弃了。当网络的吞吐量明显地小于理想的吞吐量时,网络就进入了轻度拥塞的状态。更值得注意的是,当提供的负载达到某一数值时,网络的吞吐量反而随提供的负载的增大而下降,这时网络就进入了拥塞状态。当提供的负载继续增大到某一数值时,网络的吞吐量就下降到零,网络已无法工作,这就是所谓的死锁.
- TCP进行拥塞控制的算法有四种,即慢开始、拥塞避免、快重传和快恢复。
6.1 慢开始和拥塞避免
下面讨论的拥塞控制也叫做基于窗口的拥塞控制。为此,发送方维持一个叫做拥塞窗口cwnd的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞窗口。
慢开始算法的思路
当主机开始发送数据时,由于并不清楚网络的负荷情况,所以如果立即把大量数据字节注入到网络,那么就有可能引起网络发生拥塞。较好的方法是由小到大逐渐增大拥塞窗口数值(发送窗口)。使用慢开始算法后,每经过一个传输轮次,拥塞窗口cwnd就加倍。
拥塞避免算法的思路
拥塞窗口cwnd缓慢地增大,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是像慢开始阶段那样加倍增长。因此在拥塞避免阶段就有“加法增大”特点。
当网络出现了超时(图中的点2),发送方判断为网络拥塞。于是调整门限值 ssthresh=cwnd/2=1
,同时设置拥塞窗口cwnd=1,进入慢开始阶段。
快重传算法规定,发送方只要一连收到3个重复确认,就知道接收方确实没有收到报文段M3,因而应当立即进行重传(即“快重传”),这样就不会出现超时,发送方也不就会误认为出现了网络拥塞。使用快重传可以使整个网络的吞吐量提高约20%。
6.2 主动队列管理AQM
由于队列长度总是有限的,因此当队列已满时,以后再到达的所有分组将都被丢弃。这就叫做尾部丢弃策略.
路由器中的尾部丢弃,就可能会同时影响到很多条TCP连接,结果使这许多TCP连接在同一时间突然都进入到慢开始状态这在TCP的术语中称为全局同步
为了避免发生网络中的全局同步现象,在1998年提出了主动队列管理AQM所谓“主动”就是不要等到路由器的队列长度已经达到最大值时才不得不丢弃后面到达的分组。这样就太被动了。应当在队列长度达到某个值得警惕的数值时即当网络拥塞有了某些拥塞征兆时),就主动丢弃到达的分组,其中曾流行多年的就是随机早期检测RED。