1.计算机网络的体系结构
2.运输层
-
2.1 运输层
-
协议
TCP(Transmission Control Protocol,传输控制协议) UDP(User Datagram Protocol,用户数据报协议)
-
TCP:
①TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议,其传输的单位是报文段。
②特征:面点靠工资
面向连接
只能点对点(一对一)通信
可靠交互
全双工通信
面向字节流
③TCP 如何保证可靠传输:
确认和超时重传
数据合理分片和排序
流量控制
拥塞控制
数据校验
- UDP:
①UDP(User Datagram Protocol,用户数据报协议)是 OSI(Open System Interconnection 开放式系统互联) 参考模型中一种无连接的传输层协议,提供面向事务的简单不可靠信息传送服务,其传输的单位是用户数据报。
②特征:
无连接
尽最大努力交付
面向报文
没有拥塞控制
支持一对一、一对多、多对一、多对多的交互通信
首部开销小 -
TCP与UDP的区别:
①TCP 面向连接(如打电话要先拨号建立连接),UDP 是无连接的(如广播);
②TCP 提供可靠的服务,也就是说,通过 TCP 连接传送的数据,无差错,不丢失,不重复,且按序到达;UDP 尽最大努力交付,即不保证可靠交付;
ps:TCP通过校验和,重传控制,序号标识,滑动窗口、确认应答实现可靠传输。如丢包时的重发控制,还可以对次序乱掉的分包进行顺序控制。
③TCP 的逻辑通信信道是全双工的可靠信道;UDP 则是不可靠信道;
④每一条 TCP 连接只能是点到点的;UDP 支持一对一,一对多,多对一和多对多的交互通信;
⑤TCP 面向字节流(可能出现黏包问题),实际上是 TCP 把数据看成一连串无结构的字节流;UDP 是面向报文的(不会出现黏包问题);
⑥UDP 没有拥塞控制,因此网络出现拥塞不会使源主机的发送速率降低(对实时应用很有用,如 IP 电话,实时视频会议等);
⑦TCP 首部开销20字节;UDP 的首部开销小,只有 8 个字节。 -
为什么UDP有时比TCP更有优势?
-
UDP以其简单、传输快的优势,在越来越多场景下取代了TCP,如实时游戏。
(1)网速的提升给UDP的稳定性提供可靠网络保障,丢包率很低,如果使用应用层重传,能够确保传输的可靠性。
(2)TCP为了实现网络通信的可靠性,使用了复杂的拥塞控制算法,建立了繁琐的握手过程,由于TCP内置的系统协议栈中,极难对其进行改进。 -
采用TCP,一旦发生丢包,TCP会将后续的包缓存起来,等前面的包重传并接收到后再继续发送,延时会越来越大,基于UDP对实时性要求较为严格的情况下,采用自定义重传机制,能够把丢包产生的延迟降到最低,尽量减少网络问题对游戏性造成影响。
-
TCP黏包问题
①原因
TCP 是一个基于字节流的传输服务(UDP 基于报文的),“流” 意味着 TCP 所传输的数据是没有边界的。所以可能会出现两个数据包黏在一起的情况。
②解决
plan A.发送定长包。如果每个消息的大小都是一样的,那么在接收对等方只要累计接收数据,直到数据等于一个定长的数值就将它作为一个消息。
plan B.包头加上包体长度。包头是定长的 4 个字节,说明了包体的长度。接收对等方先接收包头长度,依据包头长度来接收包体。
plan C.在数据包之间设置边界,如添加特殊符号 \r\n 标记。FTP 协议正是这么做的。但问题在于如果数据正文中也含有 \r\n,则会误判为消息的边界。
plan D.使用更加复杂的应用层协议。 -
TCP传输连接管理
①三次握手
ps:图片来自:http://www.iqiyi.com/w_19rzyvk0p1.html#curid=20868632809_f7805ef2a6c205ca9b7d4ff22113d69f
问题总结:
-
TCP其中一个可靠机制是三次握手,那么什么要三次握手?
-
握手为什么要“握三次”?
-
每次握手有什么含义?
ps:图片来自:
http://www.iqiyi.com/w_19rzyudqah.html#curid=20868774709_e1b04be2fa39659326e04f46c7debda5 -
三次握手的如何保证数据有序到达?
通过序列号和确认号,其中序列号是主机随机产生的,其后的所有都是在此基础上加一实现的。
-
如果发送的信号对方迟迟没有回应怎么办?
需要超时重传机制保证,即再次发送报文给目标主机。
-
如果刚才服务器在忙,没接受报文,但实际报文在缓存中,又一个报文过来该响应哪个呢?
由于确认号和序列号一样,只需要响应一次即可,一般不会重复响应,不过需要在设定的时间间隔内,主机收到服务器的响应,就不需要再次发出相同的请求。
ps:图片来自:
http://www.iqiyi.com/w_19rs8jdlfd.html
②四次挥手
请求方发送fin位为1的报文,被动的一方要发送第一次同意的报文,由于TCP是双通道的,两个通道中的每一个都可以收发,所以被动接受的一方在同意对方的请求后,也会将自己向对方发送消息的通道关闭,发送第二次报文,向请求方请求断开,最后请求方确认再发送报文。
ps:图片来自:
http://www.iqiyi.com/w_19rs8jdlfd.html
*参考博客:
https://blog.csdn.net/xiaobangkuaipao/article/details/76793702
https://github.com/huihut/interview
https://blog.csdn.net/cmm0401/article/details/77878998
最后的这篇博客讲的更系统一些,需要把里面的一些内容贴出来,再补充一些内容
1、UDP:
(1)UDP,user datagram protocol,用户数据报协议,不提供复杂的控制机制,利用IP提供面向无连接的通信服务,并且它是将应用程序发送过来的数据包在收到的那一刻,立即按照原样发送到上的一种机制。(2)即使在网络拥堵的情况下,UDP也无法进行流量控制等避免网络拥塞的行为。此外,在传输过程中如果出现丢包,UDP也不负责重发,甚至当数据包的到达顺序乱掉之后也没有纠正顺序的功能。因此,如果需要这些细节控制的话,就需要在采用UDP协议的应用层去作出处理。
(3)由于UDP面向无连接,所以它可以随时向对端发送数据包,再加上UDP本身的处理既简单又高效,所以UDP经常用于如下几个方面:
数据包总量比较少的通信,比如DNS、SNMP。 视频、音频等对实时性要求比较高的多媒体通信。 广播通信、多播通信。
2、TCP:
(1)TCP,控制传输协议,和UDP的差别很大,它充分实现了数据传输时的各种控制功能:针对发送端发出的数据包的确认应答信号ACK、、、针对数据包丢失或者出现定时器超时的重发机制、、、针对数据包到达接收端主机顺序乱掉的顺序控制、、、针对高效传输数据包的流动窗口控制、、、针对避免网络拥堵时候的流量控制、、、针对刚开始启动的时候避免一下子发送大量数据包而导致网络瘫痪的慢启动算法和拥塞控制。
(2)而这些在UDP中都是没有的!此外,TCP作为一种面向有连接的控制传输协议,只有在确认对端主机存在时才会发送数据,从而可以控制通信流量的浪费。
1、通过序列号和确认应答信号提高可靠性。
(1)如图1 所示:在TCP中,当接收端主机接收到来自客户端主机的数据包之后,接收端主机会返回一个已收到消息的通知,这个通知消息就叫做确认应答信号ACK包。
(2)**TCP通过肯定的确认应答信号ACK包来实现可靠的数据传输。**当发送端将数据发出之后会等待对端的确认应答。如果有确认应答,说明数据已经成功到达对端主机了。反之,若没有收到确认应答,则数据包丢失的可能性比较大。情况1:数据包丢失的情况:
如图2所示,在特定的等待时间间隔内发送端主机还是没有收到来自接收端的确认应答,发送端就可以认为数据已经丢失了,并且进行重发处理。由此,即使产生了丢包也能够保证数据到达对端,实现可靠传输。
情况2:确认应答丢失的情况:
如图3所示,未收到对端的确认应答信号并不一定意味着数据包的丢失,也有可能是因为对端主机已经收到了该数据包,但是针对该数据包的确认应答包在回送途中丢失了而已,或者没有丢失、只是因为网络中的其他一些原因延迟很长时间才到达源主机。
此时,源主机只会按照重发机制重发数据包而已,但是这对于对端主机来说简直就是灾难,因为对端主机会反复接收到很多重复的不必要的数据,而为了对上层应用协议提供可靠的传输,对端主机不得不丢掉这些重复的数据包。因此,这对网络拥塞的形成造成了很大的促进。
所以,需要一种机制来识别是否已经接收到了这个数据包、又能够判断数据包是否需要接收。
上述这些 确认应答处理、重发控制、重复处理 都可以使用数据包的序列号来进行实现。
如图4 所示,序列号 是指按照顺序给发送数据包中的每一个字节都标识上号码编号,接收端主机 根据接收数据TCP包首部中的序列号和数据长度,来将自己下一步应该接收的序列号作为确认应答返送回去。就这样,根据序列号和确认应答信号,TCP可以实现可靠传输。
2、超时重发如何确定呢?
(1)重发超时,是指在发送端主机在重发数据包之前,等待接收端主机的确认应答信号到来的“那个特定的时间间隔”。
如果超过了这个特定的时间间隔仍未收到ACK包,发送端则会进行重发。
(2)那这个特定的时间间隔如何确定呢? TCP为了保证在任何网络下都能够提供比较高的传输性能,并且在任何网络下都能够保持住这一特性,它在每次发包时都会计算往返时间及其偏差,将这个“往返时间+偏差”,重发超时就是比这个总和值要稍大一点的值。
(3)在Windows系统中,超时时间都是以0.5s 为单位进行控制的,因此超时时间都是0.5s 的整数倍。不过由于最初的数据包还不知道往返时间,所以最初的重发超时时间一般设置为6s 左右。
另外,若是进行了重发处理,则第二次、第三次的等待的超时时间会以2倍、4倍的指数函数增长,以此类推。
但是,数据包也不会倍无限次的反复的进行重发。当重发次数达到一定次数过之后,如果发送端还是接收不到对端主机的ACK包,那么发送端主机就会认为网络或者对端主机出现了异常,进行强制关闭连接,并且通知应用程序异常强制终止。
3、TCP的连接管理。
(1)TCP是面向有连接的数据通信,也就说在进行实际的数据包的收发之前,会先做好通信两端主机的准备工作:TCP三次握手!
见博客:20170906_我是如何讲清楚TCP的三次握手和四次挥手的
(2)在双端主机进行数据的交互完成过之后,会进行TCP连接的断开处理。见上面的博客。
4、TCP是以段为单位进行数据包的发送的。
(1)在建立TCP连接的同时,也可以确定发送数据包的单位,称之为“最大消息长度”:MSS。最理想的情况是,最大消息长度MSS正好是IP层中不被分片处理的最大数据长度。
(2)TCP在传送大量数据的时候,是以“段=MSS的大小”将数据进行分割发送的,进行重发时也是以MSS为单位的。
(3)如图5 所示:最大消息长度——MSS是在三次握手的时候,在两端主机之间被计算得出的。两端主机在发出“建立TCP连接请求的SYN包”时,会在SYN包的TCP首部中写入MSS选项,告诉对方自己所能够适应的MSS的大小,然后发送端主机会在两者之间选择一个较小的MSS值投入使用。
5、利用滑动窗口控制提高速度。
(1)如图6 所示:TCP是以一个段为单位进行数据的传输的,每发送一个段,就会等待对端主机的针对这个段的确认应答信号ACK,但这样的传输方式的缺点也很明显,就是:当数据包的往返时间越长,通信性能越低。
(2)为了解决这个问题,TCP引入了窗口这个概念,即使在往返时间比较长的情况下,它也能够控制网络性能的下降。如图7 所示:确认应答包不再以每个段为单位进行确认了,而是以更大的单位进行确认,转发时间将会被大幅度的缩短。也就是说,发送端主机在发送了一个段之后,没必要一直等待对端主机的确认应答信号,而是继续发送。
(3)窗口大小,指的就是无需等待接收端主机的确认应答信号而可以持续发送的数据的最大值,或者说段的最大值,比如图7 所示的窗口大小是4 个段。 滑动窗口控制的实现,使用了大量的缓冲区,通过对多个段的数据同时进行确认应答来实现高效传输。
(4)如图8 所示,发送数据中的高亮部分正是前面提到的窗口。在这个窗口内的数据即便没有收到确认应答也可以发送出去,此外发送端主机在等到对端主机的确认应答之前,必须在缓冲区中保留这部分数据,以便数据包的丢失而重发。
(5)在滑动窗口以外的数据,包括尚未发送出去的数据,以及已经确认对端收到的数据,当发送端确认对端已经收到数据包之后,此数据包就可以从缓冲区中清除了。
当收到确认应答信号过之后,会把滑动窗口的位置滑动到确认应答的序列号的位置,这样就可以顺序的将多个段同时发送以提高通信功能了。这就是滑动窗口控制。
6、滑动窗口控制与重发控制。
(1)在使用了窗口控制中,如果出现了丢包怎么办呢?
首先,我们先考虑接收端已经收到数据包只是反馈的确认应答包ACK包在途中丢失了的情况。
如图9 所示:在这种情况下,数据是已经被对端主机成功接收了的,是不需要进行重新发送的。然而,在没有使用窗口控制的前提下,没有收到确认应答包的数据包都会被重发。但是,在使用了窗口控制以后,就如图9 所示,某些应答包即使丢失了也无需重发,这也提高了传输效率。
(2)其次,我们再来考虑一下某个数据包丢失的情况。
如果当接收端主机接收到一个自己应该接收的序列号之外的数据包时,它会一直对当前接收到的数据包返回确认应答包。
因此,如图10 所示:当某一个数据包丢失以后,发送端会一直接收到序列号为1001的确认应答包,这个确认应答包好像是在提醒发送端主机“我现在想要接收的数据包序列号是1001开始的”。
因此,在滑动窗口比较大的情况下,同一个序列号的确认应答将会被重复不断地返回。而发送端主机如果 连续 3 次 接收到同一个确认应答包,就会将其对应的数据重发,这种机制比之前提到的“超时重发”更加高效,所以被称之为“高速重发控制”。
7、流量控制。
(1)发送端主机会根据自己的实际情况发送数据,而接收端也会跟据自己的实际情况接收数据。因此,TCP协议提供了这样一种机制:可以让发送端主机根据接收端主机的实际接收能力来控制自己发送的数据量。这就是所谓的“流控制”。
(2)具体操作就是:接收端主机向发送端主机通知自己所能够接收数据的大小,于是发送端主机就会发送不超过这个限度的数据,该大小被称之为“通告窗口”,就是之前提到的“控制窗口”,这个值是由接收端主机决定的。
TCP首部中,专门有一个字段用来通知“窗口大小”,接收端主机可以将自己的实际接收缓冲区大小写入到这个字段中通知给发送端,这个值越大说明网络的吞吐量越大。
不过,接收端主机的缓冲区一旦面临数据溢出,就会主动减小窗口的大小再次发送给发送端主机,从而可以控制数据发送量。也就是说,发送端主机会根据接收端主机的指示,对发送的数据量进行控制,这也就形成了一条完整的TCP流量控制。
(3)如图11 所示:当接收端主机收到了从3001号开始的数据包之后其缓冲区即将满,不得不暂时停止接收数据,于是把窗口大小设置为0,然后通知该发送端。之后,发送端在收到新的窗口更新值的通知之后通信才得以继续进行。
如果这个滑动窗口的更新通知在传输途中丢失了,则很有可能导致无法继续进行通信。为了避免此种问题的发生,发送端主机会时不时的发送一个叫做“探测窗口”的数据包,次数据包仅含有一个字节,以获取最新的窗口大小。
8、拥塞控制。
(1)有了TCP的滑动窗口控制,收发主机之间即使不再以一个“段”为单位发送确认应答信号,也能够连续发送大量数据包。然而,如果在通信刚开始的时候就发送大量的数据包,也有可能会导致其他问题。
问题的发生: 要知道,计算机网络都处在一个共享的环境中,因此也有可能是因为其他的主机之间的通信使得整个网络出现拥堵。所以,在网络拥堵时,如果突然发送一个较大量的数据包,极有可能导致网络的瘫痪。
(2)TCP为了防止这种问题的发生,在通信一开始的时候会通过一个叫做“慢启动”的算法对发送的数据量进行控制。
首先,为了在发送端调节所要发送的数据量,定义了一个叫做“拥塞窗口”的概念。于是,在慢启动刚开始的时候,把这个拥塞窗口设置为1个MSS(1个数据段)发送数据,之后每收到一个接收端主机的确认应答信号ACK包 就把这个拥塞窗口的数值加1。然后,在发送数据的时候,把拥塞窗口和滑动窗口的大小作比较,按照它们当中较小的那个值来发送比其还要小的数据量。
不过,随着数据包的每次的往返,拥塞窗口会以1、2、4、8等指数函数的增长,拥堵状况激增甚至导致网络拥塞的发生。为了防止这些,又引入了“慢启动阈值”的概念,只要拥塞窗口超过这个阈值,在每收到一个ACK包的时候,只允许以下面这种方式来增大拥塞窗口:(1个数据段的字节数的平方 / 拥塞窗口的字节数)。这样的话,拥塞窗口越大,确认应答的数目也会增加,但是其涨幅却逐渐减少,因此会导致拥塞窗口是直线形式的上升。
TCP在刚开始通信的时候,并没有设置慢启动阈值,而是在超时重发时,才会把慢启动阈值设置为当前窗口的一半大小。
(3)由重复确认应答而触发的高速重发与超时重发机制的处理是不一样的。因为前者要求至少 3 次的确认应答包到达对方主机才会触发,相比后者网络拥堵的程度较轻一些。
而由重复确认应答进行高速重发控制时,慢启动阈值的大小被设置为当时窗口大小的一半,然后将窗口大小设置为该慢启动阈值+3个MSS的大小。
(4)有了这样的一种控制过之后,TCP的拥塞窗口的变化曲线 如图12 所示。由于窗口的大小会直接影响数据被转发的吞吐量,所以一般情况下,窗口越大,越会形成高吞吐量的通信。
图可以参见这篇博客,写的更细致些:https://blog.csdn.net/qq_38950316/article/details/81087809