运输层
运输层协议概述
进程之间的通信
-
运输层的功能
- 为应用进程之间提供端到端的逻辑通信
- 对报文进行差错检测,IP首部的检验和字段只检验IP首部,运输层对这个数据报都检验。
- 复用:指发送方不同的应用程序都可以使用同一个运输层协议传送数据
- 分用指接收方的运输层在剥去报文的首部后能够把这些数据正确的交付目的主机。
-
当运输层采用面向连接的TCP协议时,尽管下面的网络是不可靠的,但这种逻辑通信信道就相当于一条全双工的可靠信道。
-
当运输层采用无连接的UDP的协议时,这种逻辑通信信道仍然是一条不可靠信道。
运输层的两个主要协议
- 用户数据报协议UDP
- 传送数据之间不需要建立连接
- 传输控制协议TCP
- 提供面向连接的服务,传送数据之前先建立连接
- 根据OSI的术语,两个对等运输实体在通信时传送的数据单元叫做运输协议数据单元TPDU
- 在TCP/IP结构中,TCP的称为TCP报文段
- 在TCP/IP结构中,UDP的称为UDP用户数据报
运输层的端口
- 端口的类型
- 硬件端口:不同设备进行交互的接口
- 软件端口:应用层的各种协议进程与运输实体进行层间交互的一种地址。
- 软件端口的分类
- 服务器端使用的端口号
- 熟知端口号(系统端口号):0~1023
- 登记端口号:1024~49151
- 客户端使用的端口号
- 短暂端口号:49152~65535
- 短暂端口号:49152~65535
- 服务器端使用的端口号
用户数据报协议UDP
UDP概述
- UDP特点
- 无连接的
- 尽最大努力交付
- 面向报文的
- 没有拥塞控制
- 支持一对一,一对多,多对一,多对多的交互通信
- 首部开销小
UDP的首部格式
- 用户数据报UDP有两个字段:数据字段和首部字段。首部字段只有8个字节,由4个字段组成,每个字段的长度都为2字节。
- UDP首部包含的字段
- 源端口:在需要对方回信时选用。不需要时为0。
- 目的端口:在终点交付报文时使用。
- 长度:UDP用户数据报的长度,最小为8字节(只有首部)。
- 检验和:检验UDP用户数据报是否有差错。有错就丢弃。
- 伪首部:计算校验和的时候所添加,并不是首部内容。伪首部既不向下传送也不向上递交,仅仅是为了计算校验和。
传输控制协议TCP概述
TCP最主要的特点
- 面向连接的
- 每一条TCP的连接时一对一的(端对端的)
- 提供可靠交付
- 面向字节流
TCP的连接
- TCP吧连接作为最基本的抽象
- TCP连接的端点叫做套接字或插口
- 套接字
- 端口拼接到IP地址即叫做套接字
- 套接字的表示:
套接字socket = (IP地址:端口)
- 每一条TCP连接唯一的被通信两端的两个端点(两个套接字)所确定:
TCP连接::={socket1,socket2}={(IP1:port1),(IP2,port2)}
可靠传输的工作原理
- 理想的传输条件有以下两个:
- 传输信道不产生差错
- 不管发送方以多快的速度发送数据,接收方总是来得及处理收到的数据。
停止等待协议
-
停止等待
- 停止等待就是每发送完一个分组就停止发送,等待对方的确认。在收到确认后再发送下一个分组。
-
无差错情况
-
出现差错
- A只要超过了一段时间仍然没有收到确认,就认为刚才发送的的分组丢失了,因而重传前面发送过的分组,这就叫做超时重传。
- A在发送完一个分组时,必须暂时保留已发送的分组的副本。
- 分组和确认分组都必须进行编号。
- 超时计时器设置的重传时间应当比数据在分组传输的平均往返时间更长一些。
-
确认丢失和确认迟到
- 出现这种情况:B的对M1的确认报文丢失了。A在超时计数器时间过期之后就重传M1,但此时B已经是收到了M1。
- 假定B又收到了A发送的M1,此时B应该采取两个行动
- 丢弃这个重复的分组M1,不向上层交付
- 向A发送确认。
-
上述的可靠传输协议常称为自动重传请求ARQ
-
信道利用率
- 停止等待协议的优点是简单,缺点是信道利用率太低
- 为了提高信道利用率,发送方可以不采用低效率的停止等待协议,而是采用流水线传输
连续ARQ协议
- 发送窗口
- 意义:位于发送窗口的5个分组都可以连续发送出去,而不需要等待对方的确认。
- 意义:位于发送窗口的5个分组都可以连续发送出去,而不需要等待对方的确认。
- 累计确认
- 接收方不必对收到的分组逐个发送确认,而是在收到几个分组后,对按序到达的最后一个分组发送确认。
- 优点:容易实现,即使丢失也不必重传。
- 缺点:不能向发送方反映出接收方已经正确收到的所有分组的信息。
TCP报文段的首部格式
- 首部固定部分各字段的意义
- 源端口和目的端口:各占2字节,分别写入源端口号和目的端口号。
- 序号:占4字节,首部序号字段值指的是本报文段所发送的数据的第一个字节的序号。
- 确认号:占4字节,是期望收到对方下一个报文段的第一个数据字节的序号。
- 数据偏移:占4位,它指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。
- 保留:占6位,保留为今后使用,但目前应设置为0。
- 紧急URG:占1位,当URG=1时,表明紧急指针字段有效。告诉系统有紧急数据,应尽快传送。
- 确认ACK:占1位,当ACK=1时确认字段才有效。连接建立后所有报文的ACK都设置为1.
- 推送PSH:占1位。
- 复位RST:占1位,当RST=1时,表示TCP连接中出现严重差错。
- 同步SYN:占1位,在连接建立是用来同步序号。
- 终止FIN:占1位,用于释放一个连接。
- 窗口:占2字节,指发送本报文段(发送方)的一方的接收窗口。
- 检验和:占2字节。
- 紧急指针:占2字节,当URG=1时才有效。指出本报文段中的紧急数据的字节数。
- 选项:长度可变,最长40字节,最短为0;
TCP可靠传输的实现
超时重传时间的选择
- 超时重传时间过短:引起报文段不必要的重传,使网络负荷增大
- 超时重传时间过长:使网络空闲时间增大,降低传输效率
- 超时重传时间RTO
- 报文段的往返时间RTT和RTT的加权平均值RTTs
- 第一测量到RTT样本时,RTTs=RTT
- α = 0.125
- RTT的偏差的加权平均值
- 第一次测量时,RTTD取值为测量到的RTT的一半
- β = 0.25
- 报文段的往返时间RTT和RTT的加权平均值RTTs
- Karm算法
- 内容:在计算加权平均值RTTs时,只要报文段重传了,就不采用其往返时间样本。这样得出的加权平均RTTs和RTO就较为准确。
- 改进:报文段每重传一次,就把RTO增大一些,典型的做法是取为原来的2倍。
TCP流量控制
利用滑动窗口实现流量控制
- 流量控制
- 所谓流量控制就是让发送方的发送速率不要太快,要让接收方来得及接收。
- 发送方的发送窗口不能超过接收方给出的接收窗口的数值。
- 流量控制中的死锁
-
B(接收端)向A(发送端)发送了零窗口报文段不久,B的接收窗口又有了一些存储空间。然后B向A发送一个窗口为400的报文段,但是这个报文段在传送过程中丢失了。然后就造成A一直等待收到B发送的非零窗口报文,而B也一直等待A发送的数据。这就是死锁。
-
解决办法:TCP为每个链接设置一个持续计数器。只要TCP连接一方一收到零窗口通知就启动持续计数器。若持续计数器时间到期,就发送一个探测报文段,而对方就在确认这个探测报文段时给出窗口值。如果窗口是0就重置持续计数器,不是0就破坏了死锁。
-
- 流量控制往往是指点对点通信量的控制,是个端到端的问题。
TCP的传输效率
- TCP报文段发送的时机
- 第一种机制是TCP维持一个变量,它等于最大报文段长度MSS。只要缓存中存放的数据达到MSS字节时,就发送出去。
- 第二种机制是由发送方的应用进程指明要求发送报文段,即TCP支持的推送操作
- 第三种机制是发送方的一个计时器期限到了,这时就把当前已有的缓存数据装入报文段。
TCP的拥塞控制
拥塞控制的一般原理
-
拥塞
- 定义:在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏,这种情况就叫做拥塞。
-
拥塞控制
- 定义:所谓拥塞控制就是防止过多的数据注入到网络中,这样就可以使网络中的路由器或链路不致过载。
- 拥塞控制是一个全局性的过程,设计到所有的主机、所有的路由器,以及与降低网络传输性能有关的所有因素。
-
从控制理论角度来分类
- 开环控制:开环控制就是在设计网络时事先将有关发生拥塞的因素考虑到,力求网络在工作时不产生拥塞。一旦整个系统运行起来,就不再中途进行改正了。
- 闭环控制:闭环控制是基于反馈环路的概念,主要有以下几种措施:
- 监测网络系统以便检测到拥塞在何时、何处发生。
- 把拥塞发生的信息传送到可采取行动的地方。
- 调整网络系统的运行已解决出现的问题。
TCP拥塞控制的方法
- 发送方维持一个叫做拥塞窗口cwnd的状态变化量。拥塞窗口的大小取决于网络的拥塞程度,并且动态的在变化,发送方让自己的发送窗口等于拥塞窗口。
- 慢开始和拥塞避免
- 慢开始算法的思路:当主机开始发送数据时,由于并不清楚主机的负载情况,所以如果立即把大量数据字节注入到网络,那么就可能引起网络拥塞。经验证明,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是说,由小到大逐渐增大拥塞窗口数值。
- 使用慢开始算法后,每经过一个传输轮次,拥塞窗口cwnd就加倍。
- 慢开始门限ssthresh
- 作用:防止慢开始算法使拥塞窗口cwnd增长过大引起网络拥塞。
- 用法
- 当cwnd<ssthresh时,使用上诉的慢开始算法
- 当cwnd>ssthresh时,停止慢开始算法而改用拥塞避免算法。
- 当cwnd=ssthresh时,既可以使用慢开始算法,也可以使用拥塞避免算法。
- 拥塞避免
- 思路:让拥塞窗口cwnd缓慢的增大,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1.
- 当拥塞避免算法遇到网络超时(网络拥塞),就将门限值ssthresh设置为cwnd/2,同时设置cwnd=1,并且重新开始慢开始算法。
- 快重传
- 采用快重传算法可以让发送方尽早知道发生个别报文段的丢失。(连续的三次确认表名丢失个个别报文段)
- 算法规定:发送方只要一连收到3个重复确认,就知道接收方确实没有收到个别报文,因而应当立即进行重传。
- 快恢复
- 一连三个确认报文表名现在只是丢失了个别的报文段,所以不启动慢开始算法,而启动快恢复算法。
- 内容:发送方调整门限值ssthresh = cwnd/2,同时设置cwnd=ssthresh,并开始执行拥塞避免算法。
主动队列管理AQM
- AQM实际就是对路由器中的分组进行智能管理,而不是简单地把队列的尾部丢弃。
TCP的运输连接管理
- 运输连接就有三个阶段,即:连接建立、数据传送和连接释放。
- 在tcp连接建立过程中要解决以下三个问题:
- 要使每一方能够却知对方的存在。
- 要允许双方协商一些参数(如窗口最大值、是否使用窗口扩大选项和时间戳选项以及服务质量等)
- 能够对运输实体资源(如缓存大小、连接表中的项目等)进行分配。
TCP的连接建立
-
一开始,B的TCP服务器进程先创建传输控制块TCB,准备接受客户进程的连接请求。然后服务器进程就处于LISTEN(监听)状态,等待客户的连接请求。如有,即作出响应。
-
A的客户进程也是首先创建传输控制块TCB。然后在打算建立TCP连接时,向B发出连接请求报文段(第一次握手报文) 。这时首部中的同步位SYN = 1,同时选择一个初始序号seq = x。TCP规定,SYN报文段(即SYN=1的报文段)不能携带数据,但要消耗掉一个序号。这时,TCP客户进程进入SYN-SENT(同步已发送)状态。
-
B收到连接请求报文段之后,如同意连接建立,则向A发送确认(第二次握手报文)。在确认报文中应把SYN和ACK都置位1,确认号是ack = x + 1,同时也要消耗掉一个序号,同时也为自己选择一个初始序号seq = y。注意,这个报文也不能携带数据,但同样要消耗掉一个序号。这时TCP服务器进程进入SYN-RCVD(同步收到)状态。
-
TCP客户收到B的确认回复后,还要给B给出确认(第三次握手报文)。确认报文段的ACK置1,确认号ack = y + 1,而自己的序号seq = x + 1。TCP规定,ACK报文段可以携带数据。但如果不携带数据则不消耗序号,在这种情况下,下一个数据报文段的序号仍是seq = x + 1。这时TCP连接已经建立,A进入ESTABLISHED(已建立)状态。
-
当B收到A的确认后,也进入ESTABLISHED状态。
-
为什么A最后还要发送一次确认呢?
- 原因:主要为了防止已失效的连接请求报文段突然又传送到了B,因而产生错误。
- 解释:
- 考虑一种正常情况,A发出的连接请求,但因连接请求报文丢失而未收到确认。于是A再重传一次连接请求。后来收到了确认,建立了连接。数据传输完毕后,就释放了连接。A共发送了两个连接请求报文段,其中一个丢失了,第二个到达了B,没有“已失效的连接请求报文段”。
- 考虑一种异常情况,即A发出的第一个连接请求并没有丢失,而是在某些网络节点长时间滞留了,以致延误到连接释放以后的某个时间段才到达B。本来这是一个早就已经失效的报文段,但B收到此失效的连接报文段后,就误认为是A又发出一次新的连接请求。于是向A发出确认报文段,同意建立连接。假定没有第三次握手,当B发出确认,新的连接就建立了。由于A并没有发出建立连接的请求,因此不会理睬B,所以也不会向B发送数据,但B却以为连接已经建立,并一直等待A发来数据。B的许多资源就这样浪费了。
TCP的连接释放
-
数据传输结束后,通信的双方都可释放连接。现在A和B都处于EXTABLISHED状态
-
A的应用进程先向其TCP发出连接释放报文段(第一次挥手),并停止再发送数据,主动关闭TCP连接。A把连接释放报文段首部的终止控制位FIN置1,其序号seq = u,它等于前面已传送过的数据的最后一个字节的序号加1.这时A进入FIN-WAIT-1(终止等待1)状态,等待B的确认。TCP规定,FIN报文段即使不携带数据,它也消耗掉一个序号。
-
B收到连接释放报文段后即发出确认(第二次挥手),确认号ack = u + 1,而这个报文段自己的序号是v,等于B前面已传过的数据的最后一个字节的序号加1。然后B就进入CLOSE-WAIT(关闭等待)状态。
-
TCP服务器进程这时应通知高层应用进程,因而从A到B这个方向的连接就释放了,这时的TCP连接处于半关闭状态,即A已经没有数据要发送了,但B若发送数据,A仍要接收。
-
A收到来自B的确认后,就进入FIN-WAIT2(终止等待2)状态,等待B发出的连接释放报文段。
-
若B已经没有要向A发送的数据,其应用进程就通知TCP释放连接。这时B发出的连接释放报文段(第三次挥手)必须使FIN=1。现假定B的序号为w(在半关闭状态下B向A又发送了一些数据)。B还必须重复上次已发送过的确认号ack = u + 1。这时B就进入LAST-ACK(最后确认)状态,等待A的确认。
-
A在收到B的连接释放报文段后,必须对此发出确认(第四次挥手)。在确认报文段中把ACK置1,确认号ack = w + 1,而自己的序号是seq = u + 1。然后进入到TIME-WAIT(时间等待)状态。
-
现在TCP连接并未释放,必须经过时间等待计时器(TIME-WAIT timer)设置的时间2MSL后,A才进入CLOSE状态。
-
为什么A在TIME-WAIT状态必须等待2MSL时间呢?
- 为了保证A发送的最后一个ACK报文能够到达B。这个ACK报文段有可能丢失,因而使出在LAST_ACK状态的B收不到对已发送的FIN+ACK的报文段的确认。B会超时重传这个FIN+ACK报文段,而A就能在2MSL时间内收到这个重传的FIN+ACK报文段。接着A再重传一次确认,重新启动2MSL计时器,最后A,B都正常进入到CLOSED状态。如果A在TIME-WAIT状态不等待一段时间,而是在发送完ACK报文段就立即释放连接,那么就无法收到B重传的FIN+ACK报文,因而也就不会重新发送一次确认。这样B就无法正常进入CLOSED状态。
- 防止“已失效的连接请求报文段”出现在本连接。A在发送完最后一个ACK报文段后,再经过时间2MSL,就可以使本连接持续的时间内产生的所有报文段都从网络中消失。这样就可以使下一个新连接中不会出现这种旧的连接请求报文段。
-
TCP的保活计时器
设想有这样的情况:客户主动与服务器建立了TCP连接,但后来客户端出现故障。显然服务器就不能接收客户端发送的数据。因此为了不让服务器白白等待,就设置了一个保活计时器。服务器每收到一次客户数据,就重新设置保活计时器,时间通常是2小时。如果两小时没有收到客户的数据,服务器就发送一个探测报文段,以后则每隔75s发送一次。若一连发送10个探测报文段后仍无客户回应,服务器就认为客户出现故障,然后关闭这个连接。