计算机网络快速入门--5--传输层

对于网络层,我们需要掌握的主要就是TCP协议和UDP协议

TCP协议和UDP协议的应用场景

TCP是一种面向连接的协议,而UDP是无连接的协议,TCP需要对数据包进行编号,并建立会话。
应用场景1:QQ聊天,udp协议
应用场景2:文件传输,tcp协议
应用场景3:访问网站,tcp协议
对于应用场景1,QQ聊天,对于一方发送消息,而另一方不必等着,这种应用场景为UDP协议。
对于应用场景2,文件传输,一个文件不可能由一些没有编号的数据包组成,那么传输到接收端的时候,组成这个文件将没有办法进行,而使用tcp协议,对数据进行拆分和编号,再组成该文件的时候按序列组成。
对于应用场景3,访问网站,对于一个网站,有些网站的数据量的非常大的,那么如果,使用udp协议,这时候,如果要在接收端组成该网站,那么也是没有办法的,但是如果使用进行编号的tcp协议,就能在访问网站数据的时候进行组合,当然网站采用的是,访问一次网站,建立连接,然后获得数据,然后释放连接的方式。

端口

我们IP数据报传输到目的地之后,怎么知道交给哪一个程序呢?比如说,你电脑上面有QQ,有浏览器,那么,收到的QQ消息怎么知道是交给QQ软件,而不会交给浏览器呢?所以,我们在IP数据报中,还需要加一个目的端口,与此就有源端口。
该端口用16位2bit来表示,那么也就是从0-65535端口。
那么如何在dos下查看开放的端口
netstat -an能查看所有建立的连接和端口号还有对应的协议。
telnet 10.234.34.234 80能测试端口是否开启,在此之前需要在控住面板中安装telnet客户端。

UDP协议

UDP协议是一种无连接的协议,尽最大努力交付的,面向报文的协议,对于UDP来说,应用层交下来多大的报文,它就转发多大的报文,即一次发送一个报文,这个报文如果太长,那么就在IP层进行分片,在一定程度上降低了效率。

这里写图片描述

UDP报文格式

这里写图片描述

UDP报文首部非常短,只占8个字节
校验和也是用的和IP数据首部校验同样的方法,只不过这里是将数据和首部一起校验。

TCP协议

TCP是面向连接的运输层协议,在传输数据之前,必须先建立连接,在传输完成之后,必须释放连接。
TCP协议的点对点的,也就是一一对应的。
TCP协议是可靠的,即无差错,不丢失,不重复,按序到达。
TCP协议提供全双工通信,由于双方都有发送缓存和接收缓存,所以当发数据的时候,如果要接数据,就像放到缓存中,如果接数据的时候,要发数据,就将要发的数据放到缓存中,这样就能实现全双工通信了。
TCP协议是面向字节流的。
TCP不关心应用进程一次发送多长的报文发送到TCP缓存中,而是根据对方给出的窗口值和当前网络的拥塞程度来决定一次发送多少个字节,也就是是,应用程序传一次只传一个字节还是一次传很多个字节,都与tcp传多少个字节无关。

这里写图片描述

TCP协议的可靠传输

停止等待协议

这里写图片描述

无差错的情况,发送一个确认一个,确认完成就接着发送第二2个。
有差错情况,发送M1,中间如果出现数据丢失了,那么就得重传,如何知道数据丢失了呢?这里在发送数据的时候,有一个超时计时器,记录发送的时候,如果超过这个时间,还没有收到确认,就认为数据丢失了,就重传一次,当然,有可能重传之后那个数据收到了,那么这时就需要一个编号,记录有没有传2次,如果这个编号与上次已经传过的编号一样的话,就丢弃。
所以,这里应当注意3点,发送一个分组之后,必须暂时保存一下,可能需要重传;分组和确认分组都必须有编号;超时计时器要比平均往返时间要长一点。
这里写图片描述

信道利用率

这里写图片描述

根据上图,我们能发现,一个分组从发送到收到确认,徐亚TD+RTT+TA的时间,TA为发送确认所需的时间。
那么可以计算出信道利用率为TD / (TD + RTT + TA),那么根据这个公式,我们知道,要提高信道利用率,必须增加TD,那么如何增加TD呢?有人说增加分组长度,这是不可取的,就好像报文交换的缺点一样,我们来看下图。

这里写图片描述

我们可以创建一个窗口,让窗口中的数据连着发,而不必确认,这时候,当收到一个确认,再让缓存区先前移动。

初探滑动窗口

这里写图片描述

从上图,我们可以看到,一开始滑动窗口发送了5个单位,当收到一个确认之后,就向前移动一格。
但是只移动一格,效率还是不高的,后面采用累积确认的方式,比如说,对于上图中,已经连续收到了3号,而4号还没收到,这时候,就发送3号的确认,而如果4号迟迟不能收到,那么就要让发送窗口退回2个单位,重新发送4和5,这叫做GO-BACK-N。
TCP的两个端都必须设置发送窗口和接收窗口,对于接收窗口而言,发送方发送过来的数据,接收放也需要用一个窗口接收,可以直接确认连续接收到的最后一个序号。

TCP报文

我们要理解TCP协议,那么我们应该重点了解TCP报文。

这里写图片描述

源端口和目的端口和UDP一样。
序号,由于TCP是面向字节的,这个序号是TCP数据部分的第一个字节的编号。
确认号,即下一个应该收到的报文序号,比如这次发过来1-100,那么下一个应该收到的是101
数据偏移,由于首部长度是可变的,这里必须指出数据从哪个字节开始,首部最大长度为60。
保留字段,目前为0,留给以后使用的。
URG,紧急标示,如果是1,标示这个报文不需要在缓存中排队,直接就能发送,如果是0,正常报文。
ACK,ACK=1时,确认号字段才有效。
PSH,PSH是尽快交付给上面的进程,而对于URG,是尽快发出去,而PSH是尽快交给接收端的进程。PSH=1时才生效。
RST,RST = 1表明TCP连接中出现了严重错误,必须释放连接,然后重新连接。这个字段在哪用呢?比如我们打开一个网页,网页还没加载完呢,就关了。
SYN,SYN = 1,表明这时候是发起建立连接,这时ACK=0,对于接收放而言,SYN = 1,表示同意接收连接,这时候ACK = 1。
FIN,FIN = 1,表示发送已经完成,要释放连接了。
对一台XP主机向web服务器的数据包图。

这里写图片描述

窗口,告诉对方,你的发送窗口应该设置成多大。如果A向B发送数据,A向告诉B,自己的接收窗口是多大,由于对方的发送窗口的大小必须小于等于自己的接收窗口(一般是等于),那么B发送窗口就必须设置成A的接收窗口一样大,而当B向A发送确认的时候,也将自己的接收窗口告诉对方,而A收到的时候,也将发送窗口设置成收和B的接收窗口大小一样。
校验和,计算法则跟UDP的一样,在计算校验和的时候,也要加上12个字节的伪首部,由于这里的TCP协议,要注意将伪首部的第4个字段的17改成16。
紧急指针,在URG=1的情况下,这个字段才有效,并标识了紧急数据的末尾在报文段中的位置。
选项字段,比如说告诉对方自己的MSS的大小,也就是自己一次性能接收多大的数据。
填充,当选项字段长度不足4个字节的时候,就在填充部分添加0。

TCP滑动窗口详解

这里以A向B发送数据为例,也就是对A的发送窗口和B的接收窗口进行分析。

这里写图片描述

在发送数据之前,先建立连接,A请求和B建立连接,A在请求报文中,附带自己的发送窗口的大小,B收到这个数据之后,就将自己的发送窗口设置成和A的接收窗口大小一样,对于B在回复建立请求连接的时候,将自己的接收窗口的大小也告诉A,那么A收到之后,将自己的发送窗口设置成B的接收窗口的大小一样。
我们截取A向B发送数据过程中的一段来分析。假设A在自己发送窗口中,发送11个数据出去,对于B暂时还没有收到,那么A还可以接着发,直到发送窗口中的数据都发出去了,而B收到A的发送数据的时候,发送窗口前移,并向B发送确认数据。A收到B的确认才能让窗口向前移动,因为这些字节要在字节的内存中保留一段时间,用来超时重传。

对于中间的数据,如果有些数据丢失了,比如在传31-41的时候,32和33先到了,那么这个时候,就把它保存在接收窗口中,过了一段时间还没收到31就发送确认号31,即31还没收到,注意,这里是选择确认,在TCP选项的字段中,可以添加哪些连续字段已经到了的信息,所以,这里就不必重发32,33了。
而如果A的发送窗口数据全发出去了,还没有收到确认,就停止等待。

这里写图片描述

对于发送缓存和接收缓存,是比发送窗口和接收窗口大的。

这里写图片描述

这里写图片描述

超时重传机制

我们知道,如果A发送数据给B,过了一段时间,B还没有发送确认,那么A就重传数据包,那么这个时间是多长呢?当然不能是随便一个时间,我们知道一个数据的往返时间叫做RTT,那么这个等待时间,肯定要比往返时间长一点,那么长多少呢?这个问题值得讨论。有人说。采取刚刚收到确认的平均值,但这也不是最好的办法, 往返时间是时刻在变的,我们不能用一个确定值。
所有就出现了加权平均值,RTTs = (1-a) * 旧的RTTS + a * 新的RTT
RFC规定这个a取值是1/8,第一次测量时就取RTT
当然这个还不能作为最终的重传时间,更可靠的计算方法是,RTO
RTO = RTTs + 4 * RTTd
而RTTd是RTT偏差的加权平均值,那么得出RTTd的计算公式
RTTd = (1-β)* (旧的的RTTd) + β * | RTTs - 新的RTT样本|
第一次成测量时,RTTd为RTT的一般。

这里写图片描述

从图能看出这种计算方法更加科学。
那么,这样就引发出一个问题,如果A发送了一个报文,B没有收到,A就重传,当A收到确认的时候,如何判断是原来报文的确认还是对重传报文的确认?
Karn指出,如果重传,就计算在呢。
而如果某段时间内,报文段经常要重传,那么RTO就得不到更新。所以又有人指出,
如果重传,就让RTO增大一倍,当网络正常的时候,就回复RTO的算法。实践证明,这种办法更有效。

这里写图片描述

TCP流量控制

所谓流量控制,就是让发送方发得不要太快,让接收放来得及接收。
接收放用一个字段rwnd来告诉发送方,rwnd大小,也就是窗口中还能接收多少数据。

这里写图片描述

从上图,我们可以看出,B在确认的时候,告诉A自己的接收窗口还能收多少数据,如果窗口满了,就让A停止发送,让接收方的应用程序先把这些数据读取出去,再发送。

死锁

在上面的流量控制的案例中,B告诉A自己的接收窗口为0了,不能再接收了,那么这时候,B就发一个报文出去,告诉A,自己的接收窗口是400了,让A继续发送数据,如果这个报文在传输的过程出了点意外丢失了,那么A就一直等着,这就是死锁。

如何打破这种僵局呢?
A有一个持续计时器,隔一段时间就给B发一个1字节的0窗口探测报文,B收到就告诉A自己的窗口值大小,如果还是0,那么计时器就重新计时。

TCP的拥塞控制

当需求的资源比实际提供的资源大时,就可能出现拥塞。
流量控制解决的是端到端的问题,而这里的一个全局性的问题。

这里写图片描述

由上图我们可以看出,如果网络吞吐量过大,就会导致拥塞,甚至死锁出现。

慢开始算法

我们用一个窗口来控制发送窗口的大小,如果一下子把它设置成很大,是很容易发生拥塞的,所以,这里就有人提出了一种慢开始算法。

这里写图片描述

慢开始算法,从1开始,让cwnd,也就是拥塞窗口的大小为1,然后成倍增加,当然不能一直成倍增加,这个过程叫做慢开始,当达到一个值的时候,也就是ssthresh,称为慢开始门限,就让cwnd一次只增加一个单位,这个过程叫做拥塞避免,当cwnd增加到一个值的时候,开始出现拥塞,这时候,就让cwnd从1重新开始计算,而ssthresh也变成开始出现拥塞值的一半。这个过程叫做乘法减小。

但是,我们的网络中,重传某个数据的现象是经常出现的,那么,对于这种情况,如果直接执行慢开始算法,对于网络的利用率是比较低的,那么有人就提出了一种叫做快重传的算法。

这里写图片描述

如上图,发送方向接收方发送数据的时候,发到M3的时候丢失了,发送方接着发送M4,M5,M6,接收放能顺利收到,并且收到一次确认一次,确认的时候任然的对M2的确认,当发送方连着收到4(加上之前确认的一个)个M2的确认的时候,重传M3,这时候,就重传M3,这就是快重传,这时候,让ssthreal值将为原来的一般,并让cwnd从开始重传的时候一半开始计算。再开始执行拥塞避免算法,这就是快恢复

这里写图片描述

发送窗口的值被接收窗口影响,又被拥塞窗口影响,那么,发送窗口的值应该取接收窗口和拥塞窗口中的较小者。

RED

在路由器中,如果接收队列满了,那么就会将后来的数据包都丢弃,这让计算机一下子变成慢开始状态,这种情况是相当不合理的。
所以,就在接收队列中设置一个最小接收门限和最大接收门限,如果累计的数据包的数量小于最小接收门限,就不丢弃,直接接收,如果大于最大接收门限,就丢弃,如果在最小接收门限和最大接收门限之间,就以一定概率丢弃。

这里写图片描述

这里写图片描述

丢弃概率与平均队列长度有关,为什么要采取平均队列长度呢?这是为了在一定程度上解决突发数据量很大,使得队列长度很大。

TCP连接的建立和释放连接

连接的建立

这里写图片描述

A是客户端,B是服务器,如果A想和B建立连接,A就发送一个建立连接的报文,这个时候A就进入了SYN-SENT状态,这个状态等待B发送确认,接着B发送确认,A收到确认之后,A就打开连接了,成了established状态。A这个时候就发送确认给B,让B也成为Established状态。
问题1:
A启动客户端,向B发送TCP连接请求,如果这个数据包在传输的过程中丢失了,那么A是超时重发还是怎样呢?
在TCP/IP详解卷1中解释,先等了大概6秒的时间超重发一次,后面等了1个24秒重发一次,再等一个24秒又重发一次。
问题2:
为什么要3次握手?
试想这样一种情况,A向B发起请求连接,而这个连接请求报文由于网络原因,需要一段时间才能到B服务器。这个时候A又发起了一次连接,而这个报文顺利到了B服务器。然后建立了连接,A和B通信完成之后,释放了连接,这个时候A的第一次发起的连接,传到了B,这个时候,又收到建立连接请求,向A发送确认,而B一直等待A对自己确认的确认,这个时候,B一直处于SYN-RCVD状态。

连接的释放

这里写图片描述

如何建立连接呢?对于A客户端,发送数据完毕,准备和断开连接,这个时候,A先发送断开连接的请求,这时候TCP就进入半关闭状态。也就是A不能向B发送数据,而B还可以向A发送数据,这时候,B向A将所有该法的数据发完之后,B就向A发送请求关闭连接的请求,A收到数据报,就回复确认,当B收到确认之后,再关闭连接。

问题1:
为什么TCP连接在关闭的时候,A向B发送了关闭请求,A进入了关闭状态,而B收到请求之后,不进入关闭状态?
原因是,这个时候,B的数据很可能没有发送完,要等到数据发完才能发起确认释放连接的请求,而这个时候,A还应该接接收B的数据。
问题2:
为什么B发送释放连接请求之后,A还应该向B发送确认?
由于A在释放连接之前,是可以接收到A的连接的,如果A不向B发送确认,那么B就不知道A有没有准备关闭,如果传给A的数据丢失了,B还应该重传给A,所以A应该给B发送一个确认,让A知道,自己已经关闭通信了。
问题3:
而为什么A还应该等一段时间呢?
对于A发出的确认,这个报文有可能会丢失,所以,需要一段时间来进行超时重传。假如这个报文传到B,在路途中丢失了,那么B就会重复给A发送释放连接的请求,那么当A收到的时候,就给B发送确认释放连接。当B收到了确认才释放连接。
问题4:
TCP四次握手的第4次,也就是A给B发确认收到B的送释放连接的请求的时候,这个报文一直发送不过去怎么办?
TCP提供了一个保活计时器,设想这样一种情况,假如A与B建立了连接,但是,如果A在通信的过程中,突然出现了故障,也就导致连接中断,而B服务器这个时候还一直等着,那么应该怎么办呢?所以,这里使用保时计时器,时间的设置通常是两个小时,如果B还没有收到A的通信,那么就自动释放连接,而一旦收到,就重新开始计时。这里也是一样的,如果这个报文一直发不过去,B等到保时计时器的时间到了,就释放连接。

猜你喜欢

转载自blog.csdn.net/qq_25956141/article/details/80106353