运输层
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/ad96e5ada12d78e5eff48d9e81595277.png#pic_center)
1. 运输层要完成的任务是什么?(功能是什么?)
运输层的功能概述:
网络层的作用是在网络上根据提供的IP地址尽最大可能来找到主机来提供主机之间的逻辑通信,而运输层是为应用进程之间提供端到端的逻辑,一个任务的执行在计算机系统中是由多个进程共同合作进行的,比如两个用户在主机上使用QQ聊天,计算机系统会运行多个进程来为QQ聊天这个功能提供保障。可能这些进程中只有一个进程是负责两个用户之间聊天的,其他的进程可能是确保一个账号不能多地登录,身份验证等。所以,运输层划分的比网络层更加细致,网络层只是主机到主机,而运输层是在主机到主机通信的前提下,两主机之间进程之间的通信(这正好符合下层为为实现上层功能提供保障的想法)。
2. 我们在运输层上,大体的把进程之间通信分为面向连接的TCP和不需要建立连接的UDP,那么分类的依据是什么?(两者的区别是什么?)
计算机运输层TCP和UDP协议的区别:
面向连接的TCP,提供一个可靠的全双工的信道,可以让目的主机接收到的信息和发送主机发送的信息完全相同。发送和接收双方之间要有协商,关于发送数据的接收,传输方式等都应该有共同的确认。接收方也要确定接受到目的方发送的数据,在通信的过程中,要不断地确认是否处在建立连接的状态,虽然会浪费很多资源,但是正是牺牲了这些资源换来了可靠的,面向连接的通信服务,所以随之而来的TCP传输的机制也就比较复杂。传输的数据单位是TCP报文段。
无连接的UDP,传送信息的速度快,效率高,但是传送信息的可靠性低。这时候的通信信道不可靠,接受方不会确认接收到目的方发送的数据。传输的数据单位是UDP报文,并未分段。
3. 网络层是实现进程之间通信的,而在发送方又有多个进程,那么怎么知道在发送方进程发送的数据一定会被接收方对应的进程所接收呢?
这里是通过端口号来实现的,端口号为了标明计算机应用层的各个进程。即两个主机之间的进程通信,首先在网络层通过IP地址找到主机在哪里,再通过端口号找到对应的进程在哪里。
端口号的分类:
(1)服务器端使用的端口号(端口号不可被重复利用)
熟知端口(固定的已经分配给上层应用协议的端口号):数值为0-1023(例如http80,ftp21/20…)
登记端口号:数值为1024-49151,非通用,为常用。
(2)客户端使用的端口号
短暂端口号:数值为49152-65535,这些端口号留给客户端口进程短暂的使用,使用完之后就会收回,以分配给其他进程使用。
当服务器进程收到客户进程的报文时,就知道客户进程所使用的动态端口号,通信结束后,这个端口号就可以共给其他客户进程使用
解决了三个问题之后就正式进入介绍TCP协议和UDP协议的环节。要想实现可靠传输,那么其中的过程不免有些复杂,而不需要建立连接的UDP协议更加简单,所以先介绍UDP。
4. UDP(不需要实现可靠传输)
UDP协议和IP协议都是提供不可靠的交付,但是一个是在运输层使用的协议,另一个是在网络层。UDP只是在IP的数据报服务之上增加了复用和分用的功能,差错检测的功能。
UDP的主要特点:无连接的,使用尽最大努力交付的,面向报文的(UDP对应用层交下来的报文,既不合并,也不拆分,只是保留报文的边界,即一次交付一个完整的报文),没有拥塞控制的,支持一(多)对一(多)。
应用程序在应用层传输下来的是应用层报文,运输层使用UDP协议在应用层报文前面加上UDP首部在传给网络层。首部有四个部分,分别为伪首部(12字节),源端口(2字节),目的端口(2字节),长度(2字节),检验和(2字节)。伪首部包括源IP地址,目的IP地址,0,17,UDP长度。在计算校验和的时候,把伪首部和用户和数据报连接在一起,仅仅是为了计算校验和,算完校验和之后就舍弃伪首部,传输之后的部分。为什么丢弃伪首部,因为在IP层会再加上新首部,里面有源和目的IP地址等信息。
5. TCP(必须实现可靠传输)
从物理层开始一层一层到传输层,每一层我们都在问一个问题:是否可以实现可靠传输?现在到了网络层,到了TCP协议这一个知识点,我们可以说,必须实现可靠传输。
5.1 首先要明白实现可靠传输的必要条件:
(1)双方必须建立连接
(2)双方只能是一对一的连接(区别于UDP)
(3)在传输的数据,不重复,不丢失,不失序
(4)提供的是全双工的通信
(5)是面向字节流的(TCP把上层传输下来的数据看为一串无结构的字节流,接收双方的字节流必须是相同的,在字节上没有丢失,重复,失序)
5.2 那么字节流是什么呢?
上层应用进程把数据按照字节流的方式传输到下层,下层要想实现接收数据的不丢失,不重复,不失序就必须接收一个字节的数据就给这个字节流编号0-n,编号结束之后,就会把数据放到发送缓冲当中去,等待发送,每次发送的字节数不相同,会受到很多影响,要综合考虑。在发送过程中不一定先发送的先到,因为正在IP层是不保证可靠传输的,但是由于发送的字节是已经编号完成的,就算接收方接收到的数据顺序不一样,也能通过编号来进行排序和判断是否有丢失的情况。
这张图可以看出来,应用进程发送的数据是有大有小的,如果是UDP协议的话,可能在前面安装上UDP首部就进行发送了,但是TCP不一样,如果数据太大的话,会把数据分为一个个数据段,形成TCP报文段进行发送。
注意:
TCP对应用进程一次把多长的报文发送到TCP的缓存中是不关心的,只会吧太长的数据块划分为短一些来进行发送;TCP会根据对方给出的窗口值和当前网络的拥塞情况来确定一个报文应该包含多少个字节。
5.3 我们所讨论的可靠传输都是建立在起点和终点之间建立了唯一的连接,那么确定连接是通过套接字来确定的,套接字socket=(IP地址:端口号)。确定完连接之后,我们就要考虑实现可靠连接的原理是什么?
TCP实现可靠传输的工作原理有两个:
停止等待协议
停止等待协议就是每发送完一个分组就停止发送,知道目的主机确认之后,并且发送主机接收到确认之后再发送下一个分组。(类似于双方打电话,一方每说一句话就加上还在吗,对方说还在,就可以继续通话)
1.无差错情况
发送方A发送一组数据到接收方B,接受方B接收到之后就会发送一个确认(ACK)给发送方A,当发送方A接收到这个ACK的时候,就会发送之后的数据。接收方是无法知道发送方发送数据的,只能被动接收。
2.出现差错
接收方B如果再接收数据的时候检测数据出现错误,或者更本没有接收到数据,那么就不会发送ACK。为了让发送方A知道发送的数据出现了问题,我们在发送方定义一个超时计数器,当发送方每发送一个数据的时候,超时计时器就会开始计时,如果发送方A在超时计时器到时间限之前收到了ACK就会发送下一个分组,如果没接收到,就会进行重发。
3.确认丢失和确认迟到
那么如果接收方接收到发来的分组之后发个发送方的ACK出现了丢失和超时的情况,都会通过超时重发来解决,但是后者在接收到第二个重复的ACK的时候,就会停止重发。
为了保障可以重发,发送方在发送完一个分组之后,必须暂时保留自己已发送的分组副本,为了确保发送方和接收方必须收到,就要把分组和确认分组都必须进行编号。超时计时器的时限应当比数据在分组发送的平均往返时间长一些。
这样发一个等待确定后再发送的机制效率低下,要想提高效率,可以采用流水线传输的方式,边发送边确认,这样的机制仍然会设置一个超时计时器。
连续ARQ协议
会在发送方设置一个发送窗口,在接收方设置一个接收窗口,这里窗口的意义是发送缓存当中的一块区域,发送方的这一块区域存放的要发送的数据,代表这一次可以连续发送的数据个数,若窗口的前面数据发送完接收方确认发送成功,那么这个发送窗口就向后移动一个数据单元。窗口滑动的过程就是不断有数据进这个窗口,也不断有数据出这个窗口,窗口中的数据按照编号大小排序,在前面的过程中,为了保证可靠传输,要求发一个数据,就要确认以下,会浪费很多时间,但是利用滑动窗口的方式,可以采用累计确认的方法来减少花费在确认上的时间,累计确认的描述如下:
因为窗口中的数据是按照编号的大小排序的,那么发送的数据不必对每个数据的分组逐个进行发送确认,而只需对按序到达的最后一个分组发送确认,只要最后一个分组确认收到之后,就能代表到这个分组为止的所有分组都正确接收到了。 使用这样方法固然可以减少时间的浪费和重传的操作,但是不能确保到最后接收到的分组之前的分组是否接收到。
若发送方发送了前5个分组,而中间的第三个分组丢失,此时接受方只能对前面两个分组发出确认,发送方不知道后面的三个分组有没有发送成功,所以就要执行Go-back-N操作,回退到第三个分组重新发送,这种操作当在线路质量不好的情况的时候,就会是使得重发频繁。
接收窗口接收到数据的时候,并不着急把接收到的数据分组提交给上层,而是要等待接收完成,且不缺少对应发送窗口中发送的数据。(个数,次序均不能错误)
综合:TCp可靠通信的具体实现
(1)TCP连接的每一端都必须设有两个窗口,分别为接收窗口和发送窗口。
(2)TCP的可靠传输机制用字节的序号进行控制,TCP所有的确认都是基于序号而不是基于报文段。
(3)TCP两端的四个窗口经常处于动态变化之中。
(4)TCP连接的往返时间RTT不是固定不变的,需要使用特定的算法估算较为合理的重传时间。
6. TCP报文段的首部格式
TCP首部的最小长度为20字节,首部成分:源端口,目的端口,序号(指的是编号之后的数据开始发送的序号),确认号(是期望收到对方的下一个报文段的数据编号的序号,确认号会在接收端发送确认回复中发回给发送端),数据偏移(数据在TCP报文那个位置开始),URG,ACK,PSH,RST,SYN,FIN,窗口(接收窗口的大小,确保用户有能力接收发送来的数据),检验和(和UDP相同,会把前面加上IP地址的伪首部),紧急指针,选项,填充。
7. TCP可靠传输的实现
- 以字节为单位的滑动窗口
接收端给发送端发送了确认报文,里面包含了窗口,确认号,当发送方接收到确认报文之后,通过窗口来了解接收方可以接收的窗口大小,以此来确定发送方下一次发送窗口的大小,通过确认号来确定发送方窗口后沿(发送窗口有后沿和前沿之分,后沿边发送边往后移动,发送完一个,就后移一个单元,传输过的数据单元必须发送端收到确认报文之后才能把发送过的数据单元移出发送窗口,一旦从发送窗口被移除的数据单元,就代表发送成功,就不会再重发)的开始地址。假设接收窗口接收的序号范围为31-50,31,32序号被接受并且发送端收到确认,但是33序号的数据单元没有被确认,可能之后的数据单元接收到了,但是接收窗口仍然认为没有接收到,如果超过了超时重传的时间还是没有收到31,32的确认,那么不管接收窗口接收到32之后的任何编号的确认,都会回退到31处开始重传(这就是发送窗口在发送完之后没有直接把数据单元给移出发送窗口的原因,否则就得从上层再获取这个数据编号的数据)。
在发送方发送窗口中的数据在发送之后只有当发送端接收到了确认才会移出发送窗口(但是这里会有缓存的存在),只要后沿移出了数据单元,那么发送窗口的前沿就能移进数据单元。
出去和进来要确保发送窗口的大小保持不变。大小随着接收窗口的大小变化而变化(保证发送方一次不能发送过多的数据导致接收方接收不了,接受不了就会丢弃,这就不是可靠传输)。如果接收窗口的大小变大了,那么发送窗口的大小也就能变大,前沿处就能多进来几个数据单元;但是如果接收端接收窗户变小了,原来处于发送端发送窗口中的数据也不能移走,只能让后沿的数据单位发送一个移出一个,前沿的数据单位不变,不允许进入,知道发送端发送窗口的大小缩小为和接收端接收窗口大小相同为止。(即前沿窗口只能扩大不能收缩)
这里也可以通过累计确认的方法减少系统开销。 - 超时重传时间的选择
超时重传时间的选择很重要,如果时间过短的话,就会导致过多的重传操作,如果时间过长的话,又会导致空闲时间过长,导致效率降低。我们这里利用加权平均往返时间来确认超时重传的时间。 - 选择却仍SACK
为了避免回退重发带来的重复重发,进行选择确认要确定边界值。(很少使用)
那么TCP的可靠传输的方法和原理我们都知道了,那么如果传输的数据太大,传输数据的总和大于了网络硬件可以提供给我们的传输数据量,这时候就会发生网络的拥塞(数据无法传送),要想解决这个问题,在TCP中,我们使用TCP的拥塞控制方法。
8. TCP的拥塞控制方法
简单的想,我们可以通过提高网络硬件来解决这个问题,但是这种方法不仅受限于成本,也不方便实施,或者控制网络数据传输的吞吐量(减少数据量的输入),那么判断网络拥塞的标志是什么呢?标准的确定很重要。出现了网络拥塞,TCP就要去减少其他发送方的发送数据量(发送窗口的大小),发送窗口的大小又是随着接受方接收窗口(接收能力)的大小来判定的,此时又新增加了一个影响因素:网络的拥堵程度,如果接收方的接收窗口很大,但是当前网络拥堵程度决定的发送量(拥塞窗口值)小的话,那么接收端的接收窗口大小应该等于当前网络的发送量,如果接收窗口的发送窗口很小的话,那么按照接收窗口的大小来发送数据。
最后发送窗口的值是由两个因素决定的,公告窗口的值可以简单获得,那么拥塞窗口CWND值的获取就需要进一步的研究。
8.1 拥塞窗口
拥塞窗口的值代表着当前网络的拥塞情况,当网络没有出翔拥塞的时候,此时的拥塞窗口的值就会变大,就可以把更多的分组发送出去,以提高网络的利用率;如果当前网络出现了拥塞,此时的拥塞窗口的值就会小,限制发送的分组,以缓解网络出现的拥塞状况。怎那么判断拥塞窗口的大小呢?
8.2 拥塞的判断
当重传定时器超时的时候就有可能出现了网络拥塞;当收到三个重复的确认ACK,比如发送方发送序号1-5的数据到接收方,发送数据1后,接收方收到了确认,但是在发送数据2后,数据2在网络中丢失了,接收方没有收到数据2,那么发送方就没有收到确认回复,发送方会继续发送3,4,5,但是接收方就会在之后接收到的数据确认回复中表示要接收2数据,接收端就会接受到三个回复确认,但是确认不正常,这样就可以确认网络可能发生了拥塞。这两种情况前者已经发生拥塞了,后者表示可能要发生拥塞了。判断出现拥塞之后,就要有一定的控制方法。
8.3 拥塞控制方法
前面说的两种拥塞情况,都可以用慢开始和拥塞避免的方法来控制,但是第二种情况更适合用快重传和块回复的方法控制。下面介绍这四种拥塞控制方法。
8.4 慢开始
发送量由小变大,在第一次传输轮次只发送一次,之后传输轮次的拥塞窗口按照指数增长。
横轴为传输轮次,纵轴为拥塞窗口,拥塞窗口的初始值为1,我们要设置一个危险的值(ssthresh)在这个值之前的拥塞窗口的值可以呈指数增长,为了让总和发送的数据最多,在ssthresh之后的值就不能指数的增大了,串口值只能一个一个的增大(因为可能在ssthresh值之后还按照指数的增长的话,到达拥塞时的轮次就会变少,与此同时发送的数据总量也就变少,我们最终的目的是让发送数据的总量最多)。让窗口的值一个一个增加,判断什么时候会发生拥塞,当通过超时(图中2)发现拥塞后,窗口的值直接恢复到最小值(由此来减少网络的负担),从新开始增加,对应的ssthresh值也会变小(一般变为上一次的一半),当通过收到三个确认(图中4)来判断发生拥塞的情况的时候,窗口值并不会减少到1,而是减少到此时的ssthresh值处开始慢慢增长(恢复快),省略了一开始的窗口增长过程(恢复慢)。所以说要发现早发现,就早恢复。所以慢重传只是通过减少拥塞的来临,依次来增加传输的轮次,让更多的数据可以传输过去。
9. TCP的运输连接管理
前面讨论了建立连接之后的可靠传输,但是TCP是如何建立连接的呢?对方是怎么知道另外一方的存在?双方要在建立连接的时候需要协商哪些必要的参数(窗口的最大值等…)?如何分配资源来确保连接?
9.1 TCP是如何建立连接的
我们这里使用客户服务器方式,主动发起建立连接的进程叫客户,而被动建立连接的进程叫做服务器。TCP建立连接的过程叫握手。要在客户和服务器之间交换三个TCP报文段才能代表连接建立成功,这个建立连接的三次报文我们称之为三握手报文。
建立三握手报文的流程(双发互相发送数据并且得到确认):
(1)发送方向接受方发送连接请求报文,同步位STN=1,选择序号seq=x,表明传送数据时候的数据字节的序号为x。
(2)接收方在收到连接请求报文后,同意后,回发确认。确认报文中SYN=1,使ACK=1,确认号ack=x+1,同时接受方也向发送方发送一个建立连接的请求,seq=y。(保证全双工)
(3)最后原发送发给接收方回一个确认报文,ACK=1,seq=x+1,ack=y+1。
当数据传送结束后,就要释放连接,释放其他占用的资源。于建立连接相同,释放连接也要相互发送释放连接报文,并且要的到确认。
9.2 TCP的连接释放
(1)当数据发送结束之后对应的发送方就会发送一个连接释放报文,确认号seq=u,接受方接收到这个连接释放报文之后会发送一个确认报文,确认编号为u的数据已经接收到了,此时就可以把接收缓存中的数据就会把数据送给上层应用进程。若原接收方的发送窗口也把数据发送完成了,就会向原发送方发送一个连接释放报文。等待源发送方的确认,确认之后双方的连接就会断开,这种连接释放就叫做四次分手。如果最后一次的握手确认没有收到,超过了超时重发的时间,就会重发,如果对方接收到了三次的握手请求,就会也知道可以进行释放。
总结:
TCP实现可靠传输:
第一步:建立连接
三握手
第二部:发送数据
窗口(序号,发送窗口+接收窗口),确认机制,流量控制(发送的数据接收方可以有能力接收),拥塞控制(发现什么时候拥塞,让拥塞来的越晚越好),超时重传…
第三步:连接释放
四握手