运输层
- 运输层协议概述
- 进程间通信
- 运输层的端口
- 运输层的两个重要协议
- 用户数据报协议UDP
- 概述
- UDP的首部格式
- 传输控制协议TCP
- TCP的主要特点
- TCP连接
- 可靠传输的工作原理
- 停止等待协议
- 信道的利用率
- 连续ARQ协议
- TCP报文段的首部格式
- TCP可靠传输的实现
- 以字节为单位的滑动窗口
- 接收窗口和缓存
- 超时重传时间的选择
- TCP的流量控制
- TCP的传输效率
- TCP的拥塞控制
- 原理
- TCP的拥塞控制方法
- TCP的运输连接管理
- TCP的连接建立
- TCP的连接释放
- 文章notion链接
运输层协议概述
进程间通信
从通信和信息处理的角度看,运输层向它上面的应用层提供通信服务,它属于面向通信部分的最高层,同时也是用户功能中的最低层。当网络的边缘部分中的两台主机使用网络的核心部分的功能进行端到端的通信时,只有主机的协议栈才有运输层,而网络核心部分中的路由器在转发分组时都只用到下三层的功能。
从IP层来说,通信的两端是两台主机。真正进行通信的实体是在主机中的进程,是这台主机中的一个进程和另一台主机中的一个进程在交换数据(即通信)。因此严格地讲,两台主机进行通信就是两台主机中的应用进程互相通信。
从上图就可以看出网络层和运输层有明显的区别:网络层为主机之间提供逻辑通信,而运输层为应用进程之间提供端到端的逻辑通信。
运输层的端口
在一台主机中经常有多个应用进程同时分别和另一台主机中的多个应用进程通信。因此运输层就有两个很重要的功能:
- 复用:是指在发送方不同的应用进程都可以使用同一个运输层协议传送数据(需要加上适当的 首部)
- 分用:指接收方的运输层在剥去报文的首部后能够把这些数据正确交付目的应用进程
而为了使运行不同操作系统的计算机的应用进程能够互相通信,就必须用统一的方法对TCP/IP体系的应用进程进行标志。那就在运输层使用协议端口号,简称为端口。运输层用16位端口号来标志一个端口,且端口号只具有本地意义,因此两个计算机中的进程要互相通信,不仅必须知道对方的IP地址,而且要知道对方的端口号。运输层的端口号可以分为两大类:
- 服务器端使用的端口号
- 客户端使用的端口号
运输层的两个重要协议
在TCP/IP体系中,运输层的两个主要协议都是互联网的正式标准:
-
用户数据报协议:UDP(User Datagram Protocol)
UDP在传送数据之前不需要先建立连接。远地主机的运输层在收到UDP报文后,不需要给出任何确认。虽然UDP不提供可靠交付,但在某些情况下UDP却是一种最有效的工作方式。
-
传输控制协议:TCP(Transmission Control Protocol)
TCP则提供面向连接的服务。在传送数据之前必须先建立连接,数据传送结束后要释放连接。TCP不提供广播或多播服务。由于TCP要提供可靠的、面向连接的运输服务,因此不可避免地增加了许多的开销,这不仅使协议数据单元的首部增大很多,还要占用许多的处理机资源。
用户数据报协议UDP
概述
用户数据报协议UDP只在IP的数据报服务之上增加了很少一点的功能,这就是复用和分用的功能以及差错检测的功能。UDP的主要特点是:
- UDP是无连接的,即发送数据之前不需要建立连接,当然,发送数据结束时也没有连接可释放,因此减少了开销和发送数据之前的时延。
- UDP使用尽最大努力交付,即不保证可靠交付,因此主机不需要维持复杂的连接状态表。
- UDP是面向报文的。发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付给IP层,它,既不合并,也不拆分,而是保留这些报文的边界。这就是说,应用层交给UDP多长的报文,UDP就照样发送,一次发送一个报文。
- UDP没有拥塞控制,因此网络出现的拥塞不会使源主机的发送速率降低。当某些应用要求源主机以恒定的速率发送数据,并且允许在网络发生拥塞时丢失一些数据,但却不允许数据有太大的时 延。UDP正好适合这种要求。
- UDP支持一对一、一对多、多对一和多对多的交互通信。
- UDP的首部开销小,只有8个字节,比TCP的20个字节的首部要短。
UDP的首部格式
用户数据报UDP有两个字段:数据字段和首部字段。
- 首部
首部字段有8个字节,由四个字段组成。各字段意义如下:
- 源端口:源端口号。在需要对方回信时选用。不需要时可用全0。
- 目的端口:目的端口号。这在终点交付报文时必须使用。
- 长度:UDP用户数据报的长度,其最小值是8 (仅有首部)。
- 检验和:检测UDP用户数据报在传输中是否有错。有错就丢弃。
当运输层从IP层收到UDP数据报时,就根据首部中的目的端口,把UDP数据报通过相应的端口,上交到相应的应用进程。
如果接收方UDP发现收到的报文中的目的端口号不正确,就丢弃该报文,并由网际控制报文协议ICMP发送“端口不可达”差错报文给发送方。
- 计算检验和
在计算检验和时,要在UDP用户数据报之前临时增加12个字节的伪首部,得到一个临时的UDP用户数据报。检验和就是按照这个临时的UDP用户数据报来计算的。伪首部既不向下传送也不向上递交,仅仅是为了计算检验和。
UDP计算检验和的方法和计算IP数据报首部检验和的方法相似。但不同的是:IP数据报的检验和只检验IP数据报的首部,但UDP的检验和是把首部和数据部分一起都检验。
检验方法
发送方:先把全零放入检验和字段。再把伪首部以及UDP用户数据报看成是由许多16位的字串接起来的。若UDP用户数据报的数据部分不是偶数个字节,则要填入一个全零字节(但此字节不发送)。然后按二进制反码计算出这些16位字的和。将此和的二进制反码写入检验和字段后,然后就发送这样的UDP用户数据报。
接收方:把收到的UDP用户数据报连同伪首部(以及可能的填充全零字节)一起,按二进制反码求这些16位字的和。当无差错时其结果应全为1,否则就表明有差错出现,接收方就应丢弃这个UDP用户数据报。
传输控制协议TCP
TCP的主要特点
- TCP是面向连接的运输层协议。即应用程序在使用TCP协议之前,必须先建立TCP连接。在传送数据完毕后,必须释放已经建立的TCP连接。就像打电话一样。
- 每一条TCP连接只能有两个端点,即每一条TCP连接只能是点对点的。
- TCP提供可靠交付的服务。通过TCP连接传送的数据,无差错、不丢失、不重复, 并且按序到达。
- TCP提供全双工通信。TCP允许通信双方的应用进程在任何时候都能发送数据。TCP连接的两端都设有发送缓存和接收缓存,用来临时存放双向通信的数据。在发送时,应用程序在把数据传送给TCP的缓存后,就可以做自己的事,而TCP会在合适的时候把数据发送出去。在接收时,TCP把收到的数据放入缓存,上层的应用进程在合适的时候读取缓存中的数据。
- 面向字节流。
TCP连接
TCP把连接作为最基本的抽象。前面讲过,每一条TCP连接有两个端点,而TCP连接的端点叫做套接字(socket),端口号拼接到IP地址后即构成了套接字,即:套接字socket = (IP地址:端口号)
而每一条TCP连接唯一地被通信两端的两个端点所确定,那么:TCP连接 = { socket 1, socket2 } = { (IP地址1:端口号1),(IP地址2:端口号2) }
可靠传输的工作原理
TCP发送的报文段是交给IP层来传送的。但IP层只能提供尽最大努力服务,也就是说,TCP下面的网络所提供的是不可靠的传输。因此,TCP必须釆用适当的措施(使用一些可靠的传输协议)才能使得两个运输层之间的通信变得可靠:在出现差错时让发送方重传出现差错的数据;在接收方来不及处理收到的数据时,及时告诉发送方适当降低发送数据的速度。
停止等待协议
全双工通信的双方既是发送方也是接收方。“停止等待”就是每发送完一个分组(传送的数据单元)就停止发送,等待对方的确认。在收到确认 后再发送下一个分组。
- 无差错情况
如上图(a),A发送分组M1,发完就暂停发送,等待B的确认。B收到了M1就向A发送确认。A在收到了对M1的确认后,就再发送下一个分组M2。
- 出现差错
如上图(b),B接收M1时检测出了差错,就丢弃 M1,其他什么也不做。A只要超过了一段时间仍然没有收到B的确认,就认为刚才发送的分组丢失了, 因而重传前面发送过的分组。这就叫做超时重传。要实现超时重传,就要在每发送完一个分组时设置一个超时计时器。如果在超时计时器到期之前收到了对方的确认,就撤销已设置的 超时计时器。
注意:
- A在发送完一个分组后,必须暂时保留已发送的分组的副本(在发生超时重传时使用)。只有在收到相应的确认后才能清除暂时保留的分组副本。
- 分组和确认分组都必须进行编号。这样才能明确是哪一个发送出去的分组收到了确认,而哪一个分组还没有收到确认。
- 超时计时器设置的重传时间应当比数据在分组传输的平均往返时间更长一些。
- 确认丢失和确认迟到
如上图(a),B所发送的对M1的确认丢失了。A在设定的超时重传时间内没有收到确认,并无法知道是自己发送的分组出错、丢失,或者是B发送的确认丢失了。因此A在超时计时器到期后就要重传M1。B又收到了重传的分组M1后,应采取两个行动:
- 丢弃这个重复的分组M1,不向上层交付。
- 向A发送确认。
如上图(b),传输过程中没有出现差错,但B对分组M1的确认迟到了。此时A会收到重复的确认。而A对重复的确认的处理方式是收下后就丢弃,但是B仍然会收到重复的M1,并且同样要丢弃重复的M,并重传确认分组。
信道的利用率
停止等待协议的优点是简单,但缺点是信道利用率太低。
为了提高传输效率,发送方可以不使用低效率的停止等待协议,而是釆用流水线传输。流水线传输就是发送方可连续发送多个分组,不必每发完一个分组就停顿下来等待对方的确认。这样可使信道上一直有数据不间断地在传送。这种传输方式可以获得很高的信道利用率。当使用这种方法时就要用到连续ARQ协议和滑动窗口协议。
连续ARQ协议
如图,位于发送窗口内的5个分组都可连续发送出去,而不需要等待对方的确认,这样信道利用率就提高了。发送方每收到一个确认,就把发送窗口向前滑动一个分组的位置。而接收方一般都是釆用累积确认的方式:在收到几个分组后,对按序到达的最后一个分组发送确认,这就表示到这个分组为止的所有分组都已正确收到了。累积确认的优点在于容易实现,即使确认丢失也不必重传;缺点在于如果发送方发送了前5个分组,而中间的第3个分组丢失了。这时接收方只能对前两个分组发出确认。发送方无法知道后面三个分组的下落,而只好把后面的三个分组都再重传一次。
TCP报文段的首部格式
一个TCP报文段分为首部和数据两部分,TCP报文段首部的前20个字节是固定的,也是TCP首部的最小长度,后面有4n字节是根据需要而增加的选项。
- 源端口和目的端口:分别写入源端口号和目的端口号。
- 序号:TCP是面向字节流的。在一个TCP连接中传送的字节流中的每一个字节都按顺序编号。首部中的序号字段值则指的是本报文段所发送的数据的第一个字节的序号。
- 确认号:是期望收到对方下一个报文段的第一个数据字节的序号。
- 数据偏移:它指出TCP报文段的数据起始处距离TCP报文段的起始处有多远。这个字段实际上是指出TCP报文段的首部长度。
- 保留:保留为今后使用,但目前应置为0。
- 紧急URG:当URG=1时,它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据),而不要按原来的排队顺序来传送。
- 确认ACK:仅当ACK=1时确认号字段才有效。当ACK=0时,确认号无效。在连接建立后所有传送的报文段都必须把ACK置1。
- 推送PSH:当两个应用进程进行交互式的通信时,有时在一端的应用进程希望在键入一个命令后立即就能够收到对方的响应,就可以把PSH置1。
- 复位RST:当RST=1时,表明TCP连接中出现严重差错,必须释放连接,然后再重新建立运输连接。
- 同步SYN:在连接建立时用来同步序号。
- 终止FIN:用来释放一个连接。
- 窗口:窗口指的是发送本报文段的一方的接收窗口。它明确指出了现在允许对方发送的数据量,这个值经常在动态变化着。
- 检验和:检验的范围包括首部和数据这两部分。和UDP一样,在计算检验和时,要在TCP报文段的前面加上12字节的伪首部。
- 紧急指针:URG = 1时,它指出本报文段中的紧急数据的字节数。
- 选项:长度可变,最长可达40字节。
TCP可靠传输的实现
以字节为单位的滑动窗口
TCP的滑动窗口是以字节为单位的。现假定A收到了B发来的确认报文段,其中窗口是20字节,而确认号是31,根据这两个数据,A就构造出自己的发送窗口:
显然,窗口越大,发送方就可以在收到对方确认之前连续发送更多的数据,因而可能获得更高的传输效率。发送窗口的位置由窗口前沿和后沿的位置共同确定。发送窗口的后沿可能会不动(没有收到新的确认)或前移(收到了新的确认),但不会后退,因为不能撤销掉己收到的确认。发送窗口前沿通常是不断向前移动,但也有可能不动。要描述一个发送窗口的状态需要三个指针:
接收窗口和缓存
前面有说到:发送方的应用进程把字节流写入TCP的发送缓存,接收方的应用进程从TCP的接收缓存中读取字节流。
发送缓存用来暂时存放:发送应用程序传送给发送方TCP准备发送的数据和TCP己发送出但尚未收到确认的数据。发送应用程序必须控制写入缓存的速率不能太快,否则发送缓存就会没有存放数据的空间。
接收缓存用来暂时存放:按序到达的、但尚未被接收应用程序读取的数据和未按序到达的数据。如果收到的分组被检测出有差错,则要丢弃。如果接收应用程序来不及读取收到的数据,接收缓存最终就会被填满,使接收窗口减小到零。反之,如果接收应用程序能够及时从接收缓存中读取收到的数据,接收窗口就可以增大,但最大不能超过接收缓存的大小。
超时重传时间的选择
运输层的超时计时器的超时重传时间RTO究竟应设置为多大呢?TCP釆用了一种自适应算法:
其中RTTS是一个加权平均往返时间(RTT是一个报文段发出的时间减去其收到相应的确认的时间):
而RTTD是RTT的偏差的加权平均值:
TCP的流量控制
所谓流量控制就是让发送方 的发送速率不要太快,要让接收方来得及接收。
若B向A发送了零窗口的报文段后不久,其接收缓存又有了一些存储空间。于是B向A发送了rwnd=400的报文段,然而这个报文段在传送过程中丢失了。A一直等待收到B发送的非零窗口的通知,而B也一直等待A发送的数据。如果没有其他措施,这种互相等待的死锁局面将一直延续下去。
为了解决这个问题,TCP为每一个连接设有一个持续计时器,只要 TCP连接的一方收到对方的零窗口通知,就启动持续计时器。若持续计时器设置的时间到期,就发送一个零窗口探测报文段(仅携带1字节的数据),而对方就在确认这个探测报文段时给出了现在的窗口值。如果窗口仍然是零,那么收到这个报文段的一方就重新设置持续计时器。如果窗口不是零,那么死锁的僵局就可以打破了。
TCP的传输效率
应用进程把数据传送到TCP的发送缓存后,剩下的发送任务就由TCP来控制了。那么如何控制TCP报文段的发送时机?可以使用如下的机制:
- TCP维持一个变量,它等于最大报文段长度MSS,只要缓存中存放的数据达到MSS字节时,就组 装成一个TCP报文段发送出去。
- 由发送方的应用进程指明要求发送报文段, 即TCP支持的推送(push)操作。
- 发送方的一个计时器期限到了,这时就把当前已有的缓存数据装入报文段(但长度不能超过MSS)发送出去。
- Nagle算法:若发送应用进程把要发送的数据逐个字节地送到TCP的发送缓存,则发送方就把第一个数据字节先发送出去,把后面到达的数据字节都缓存起来。当发送方收到对第一个数据字符的确认后,再把发送缓存中的所有数据组装成一个报文段发送出去,同时继续对随后到达的数据进行缓存。
TCP的拥塞控制
原理
在计算机网络中的链路容量(即带宽)、交换结点中的缓存和处理机等,都是网络的资源。在某段时间,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就会变坏。这种情况就叫做拥塞。而拥塞控制就是防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不致过载。进行拥塞控制需要付出代价。首先就需要获得网络内部流量分布的信息。在实施拥塞控制时,还需要在结点之间交换信息和各种命令,以便选择控制的策略和实施控制。这样就产生了额外开销。因此在设计拥塞控制策略时,必须全面衡量得失。
TCP的拥塞控制方法
TCP进行拥塞控制的算法有四种:慢开始、拥塞避免、快重传和快恢复
- 慢开始
慢开始算法的思路是这样的:当主机开始发送数据时,由于并不清楚网络的负荷情况,所以如果立即把大量数据字节注入到网络,那么就有可能引起网络发生拥塞。经验证明,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是由小到大逐渐增大拥塞窗口(cwnd)的数值。每收到一个对新的报文段的确认后,可以把拥塞窗口进行增加:
其中N是原先未被确认的、但现在被刚收到的确认报文段所确认的字节数。SMSS是送方的最大报文段的数值。
慢开始的“慢”并不是指cwnd的增长速率慢,而是指在TCP开始发送报文段时先设置cwnd=1,使得发送方在开始时只发送一个报文段(目的是试探一下网络的拥塞情况),然后再逐渐增大cwnd,每经过一个传输轮次(往返时间RTT),cwnd就加倍。。这当然比设置大的cwnd值一下子把许多报文段注入到网络中要“慢得多”,但是这对防止网络出现拥塞是一个非常好的方法。
- 拥塞避免
拥塞避免算法的思路是让拥塞窗口cwnd缓慢地增大,即每经过一个往返时间RTT就把发送方的拥塞窗口 cwnd加1,而不是像慢开始阶段那样加倍增长。
如上图1号点,当拥塞窗口cwnd增长到慢开始门限值ssthresh时,就改为执行拥塞避免算法,拥塞窗口按线性规律增长,使网络比较不容易出现拥塞,并非完全能够避免了拥塞。
如上图2号点,若当拥塞窗口cwnd=24时网络出现了超时,发送方判断为网络拥塞,于是会调整门限值ssthresh=cwnd/2=12,同时设置拥塞窗口cwnd=1,重新进入慢开始阶段。
如上图4号点,发送方一连收到3个对同一个报文段的重复确认。有时个别报文段会在网络中丢失,但实际上网络并未发生拥塞。如果发送方迟迟收不到确认,就会产生超时,就会误认为网络发生了拥塞。这就导致发送方错误地启动慢开始,因而降低了传输效率。而釆用快重传算法可以让发送方尽早知道发生了个别报文段的丢失。
- 快重传
快重传算法首先要求接收方不要等待自己发送数据时才进行捎带确认,而是要立即发送确认,即使收到了失序的报文段也要立即发出对已收到的报文段的重复确认。
快重传算法规定,当发送方只要一连收到3个重复确认,就知道接收方确实没有收到报文段M3,因而应当立即进行重传,这样就不会出现超时,发送方也不就会误认为出现了网络拥塞,此后执行快恢复算法,发送方调整门限值ssthresh=cwnd/2=8,并重新开始拥塞控制。
- 快恢复
如上上图5号点,发送方知道现在只是丢失了个别的报文段,于是不启动慢开始,而是执行快恢复算法,即之间执行拥塞避免。也有的快恢复实现是把快恢复开始时的拥塞窗口cwnd值在原基础上加上3 x MSS(报文段的长度)。
TCP的运输连接管理
TCP是面向连接的协议。运输连接是用来传送TCP报文的。TCP运输连接的建立和释放是每一次面向连接的通信中必不可少的过程。因此,运输连接就有三个阶段:连接建立、数据传送和连接释放。在TCP连接建立过程中要解决以下三个问题:
- 要使每一方能够确知对方的存在。
- 要允许双方协商一些参数。
- 能够对运输实体资源(如缓存大小等)进行分配。
TCP的连接建立
TCP建立连接的过程叫做握手,握手需要在客户和服务器之间交换三个TCP报文段。这个过程称为三次握手:
- 一开始,B的TCP服务器进程先创建传输控制块TCB,然后服务器进程就处于LISTEN监听状态,等待客户的连接请求。
- A的TCP客户进程也是首先创建传输控制模块TCB,然后在打算建立TCP连接时, 向B发出连接请求报文段。设置首部中的同步位SYN=1,同时选择一个初始序号seq=x。
- B收到连接请求报文段后,如同意建立连接,则向A发送确认。在确认报文段中应把SYN位和ACK位都置1,择一个初始序号seq=y,确认号是ack=x+1。
- TCP客户进程收到B的确认后,最后还要向B给出确认。确认报文段的ACK置1,确认号ack=y+l,而自己的序号seq = x+1。这一次握手这主要是为了防止”己失效的连接请求报文段“突然又传送到了 B,因而产生错误。
TCP的连接释放
数据传输结束后,通信的双方都可释放连接。这个过程称为四次挥手:
开始A和B都处于ESTABLISHED状态。
- A的应用进程先向其TCP发出连接释放报文段,并停止再发送数据,主动关闭TCP连接。A把连接释放报文段首部的终止控制位FIN置为1,其序号seq=u(等于前面已传送过的数据的最后一个字节的序号加1)。这时A进入FIN-WAIT-1(终止等待1)状态,并等待B的确认。
- B收到连接释放报文段后即发出确认,确认号是ack=u+1,而这个报文段自己的seq是v(等于B前面已传送过的数据的最后一个字节的序号加1)。然后B就进入CLOSEWAIT(关闭等待)状态。TCP服务器进程这时应通知高层应用进程,因而从A到B这个方向的连接就释放了,这时的TCP连接处于半关闭(half-close)状态,即A已经没有数据要发送了,但B若发送数据,A仍会接收。
- A收到来自B的确认后,就进入FIN-WAIT-2(终止等待2)状态,等待B发出的连接释放报文段。
- 若B己经没有要向A发送的数据,其应用进程就通知TCP释放连接。这时B发出的连接释放报文段必须使FIN=1。现假定B的seq为w(在半关闭状态B可能又发送了一些数据)。B还必须重复上次已发送过的确认号ack=u+1。这时B就进入LAST-ACK (最后确认)状态,等待A的确认。
- A在收到B的连接释放报文段后,必须对此发出确认。在确认报文段中把ACK置1, 确认号ack=w+1,而自己的序号是seq=u+1。然后进入到TIME-WAIT(时间等待)状态。请注意,现在TCP连接还没有释放掉。必须经过时间等待计时器设置的时间2MSL后,A才进 入到CLOSED状态。
为什么A在TIME-WAIT状态必须等待2MSL的时间呢?一是为了保证A发送的最后一个ACK报文段能够到达B;二是防止上一节提到的“己失效的连接请求报文段”出现在本连接中。
除时间等待计时器外,TCP还设有一个保活计时器,这是为了防止客户己主动与服务器建立了TCP连接后客户端的主机突然出故障的情况,显然此时服务器以后就不能再收到客户发来的数据。因此,应当有措施使服务器不要再白白等待下去。服务器每收到一次客户的数据,就重新设置保活计时器,时间的设置通常是两小时。若两小时没有收到客户的数据,服务器就发送一个探测报文段,以后则每隔 75秒钟发送一次。若一连发送10个探测报文段后仍无客户的响应,服务器就认为客户端出了故障,接着就关闭这个连接。
文章notion链接
https://www.notion.so/5851c1a379bb4b819731aa41d701d38c
本文资料全部来自于计算机网络(第7版)