传输层重要协议:UDP协议和TCP协议
求求留下一个赞~❤️❤️❤️❤️❤️❤️❤️❤️
目录
1.UDP报文格式
2.UDP协议特点
二、TCP协议
1.TCP报文格式
2.TCP原理
(1)确认应答机制
(2)超时重传机制
(3)连接管理机制(面试必考)(三次握手,四次挥手)
(4)滑动窗口(效率机制)
(5)流量控制
(6) 拥塞控制
(7)延时应答(效率机制)
(8)捎带应答
(9)面向字节流(粘包问题)
(10)异常情况
(10)异常情况
三、TCP和UDP的差别
一、UDP协议
1.UDP报文格式
源ip,源端口:数据从哪里来
目的ip,目的端口:数据到哪里去
举例:
每个端口号在UDP报文里面,占用两个字节,端口号的取值范围一般是0 ~ 65535,其中 < 1024的端口,称为“知名端口号”,给一些名气较大的服务器预留的端口,平时联系写代码我们应该使用1024以后的端口号。
当端口号取值65535时,此时UDP报文长度处于最大,为64KB。
UDP校验和:当进行数据传输时,如果有外部环干扰,比如强磁场之类的情况,就可能导致低电平转换为高电平,导致比特翻转,此时数据传输就会出错误。此时校验和存在的意义就是为了判断当前传输的数据是否是错误。校验和往往是取内容或者内容的一部分,通过一些算术运算,数学公式变换,得到的一个数值。如果内容发生改变,得到的校验和也就改变了。
当校验和不对时,此时传输的数据一定是不对的,
如果校验和是对的,此时传输的数据也有一定概率不对。
校验和过程:
一般发送方将载荷数据带入到校验和算法中,计算生成了校验和结果,将这个校验和结果设置为sum1
然后发送方将这个数据发送给了接收方,当接收方收到数据,既有载荷,也有校验和sum1,接收方就把载荷数据按照与发送方使用的相同算法,在计算了一边校验和,此时得到sum2
最后对比sum1和sum2是否相同,如果相同,那么这个数据可能就没有问题,如果相同,那么数据一定就出现了问题。
2.UDP协议特点
UDP:无连接,不可靠传输,面向数据报,全双工
无连接:使用UDP/TCP通信的双方,各自是否需要刻意保存对端的相关信息;
不可靠传输:信息发出去,不关注结果,不关注是否传输过去。没有任何安全机制,发送端发送数据报以后,如果因为网络故障该段无法发到对方,UDP协议层也不会 给应用层返回任何错误信息;
面向数据报:以一个UDP数据报为传输的基本单位,应用层交给UDP多长的保温,UDP原样发送,既不会拆分,也不会合并。
全双工:一条路径双向通信,既能读,也能写
大小受限:UDP协议首部中有一个16位的最大长度。也就是说一个UDP能传输的数据最大长度是64K(包含UDP首 部)。
缓冲区:UDP只有接收缓冲区,没有发送缓冲区。
二、TCP协议
1.TCP报文格式
源端口/目的端口:数据从哪里来,数据到哪里去
序号(sequence number):seq序号,占32位,用来标识从TCP源端向目的端发送的字节流,发起方发送数据时对此进行标记。
确认号(acknowledgement number):ack序号,占32位,只有ACK标志位为1时,确认序号字段才有效,ack = seq+1。
标志位:共六个:默认为0
URG:紧急指针是否有效
ACK:确认号是否有效(小写ack为确认序号)
PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走
RST:对方要求重新建立连接;把携带RST表示的称为复位报文段
SYN:请求建立连接;把携带SYN的表示称为同步报文段
FIN:通知对方,本段要关闭了,将携带FIN表示的为结束报文段
校验和:发送端填充,CRC校验。接收端校验不通过,则认为数据有问题。此处的检验和不光 包含TCP首部,也包含TCP数据部分
紧急指针:标识哪部分数据是紧急数据
2.TCP原理
(1)确认应答机制
确认序号对应的规则:接收方取发送方发过来的所有数据的最后一个字节的下一个字节的序列号,这是一个无实际意义的数据。接收方可以通过确认序号ack,告诉发送方哪些数据已经收到了。
确认序号1001的含义:
< 1001的数据,接收方已经收到
接收方接下来向发送方发送的数据是从1/在//001序号开始的
每一个ACK都带有对应的确认序列号,意思是告诉发送者,已经收到了哪些数据,下一次从哪里开始发送。
(2)超时重传机制
丢包:数据在网络中是被分成一个个数据包传输的,每个数据包中都有表示数据的信息和提供 数据路由的桢,而数据包在一般介质中传播是总有一小部分由于两个终端的距离过大会丢失,这个过程叫做丢包。
以下是两种丢包情况:
发送方发送数据时丢包:
其中,主机A发送数据给B之后,可能会因为网络拥堵卡顿等原因,导致数据或一部分数据无法到达主机B,造成丢包;
当主机A在一个特定的事件间隔内没有收到B发来的确认应答(ACK),就会进行重发。
应答报文返回时丢包:
当主机A未收到确认应答,也可能是ACK丢失了。
在这种问题下,A重发数据,会导致B出现重复的数据,为了避免B重复收到数据,TCP会在接收缓冲区中根据收到的数据的序号,进行去重,保证了应用程序督导的数据仍然只有一份。
如果重传的数据继续丢失,TCP会继续超时重传,但是每次丢包一次,超时等待时间就会变长,重传的概率也就会变低,如果一直传不过去(此时网络已经出现了严重的问题)
连续多次重传,都无法得到ACK回应,此时TCP会放弃重传,选择尝试重置连接,也就是尝试重连,如果重置连接也失败了,TCP就会关闭连接,放弃网络通信。
TCP是如何实现可靠性的?答:确认应答,超时重传。
(3)连接管理机制(面试必考)(三次握手,四次挥手)
正常情况下,TCP要经过三次握手建立连接,四次挥手断开连接。
三次握手 - 建立连接介绍
握手(handshake)指的是通信双方,进行一次网络交互,三次握手就相当于客户端和服务器之间,通过了三次交互,进行了连接关系。
SYN:请求建立连接;把携带SYN的表示称为同步报文段
三次握手过程(含模拟场景)
发送方(第一次):你愿意做我的朋友么吗?
客户端发送SUN同步报文段,向服务器这边申请建立连接
接收方(第二次):我愿意(返回ACK),你愿意做 我的朋友么(再次核对)
服务器返回应答ACK,同时向客户端发送一个SYN
发送方(第三次):我愿意
再次发送一个SYN
以上看似是四次握手,但是中间的两次可以合并(SYN + ACK)成一次发送,所以是三次握手
三次握手的目的:使双方都确认了自己是对方的唯一,三次握手验证了客户端和服务器,各自的发送能力和接收能力是否正常,使后续可靠传输的基础。
关于标志位:
默认:都为0。
如果设置为1,则表示特定含义:
其中第二位,是ACK,如果这一位是1,表示当前TCP数据报是一个应答报文。
其中第五位,是SYN,如果这一位是1,当前TCP是一个同步报文。
也就是,如果一个TCP数据包,第二位和第五位都是1,则当前报文时SYN和ACK。
四次挥手 - 断开连接介绍
通信双方,各自给对方发送一个FIN(结束报文),再各自给对方返回ACK。
这里的ACK和FIN不可以合并。
三次握手中,ACK和SYN是同时机触发的,都是由内核来完成的(应用程序无法干预,程序员无法改变)。
四次挥手中,ACK和FIN是不同实际触发的,ACK是内核来完成的,会在收到FIN的时候第一时间返回,FIN则是应用程序代码控制的,在调用到socket的close方法的时候才会触发到FIN,俩个报文触发的时机不一样,也就不能合并。
(4)滑动窗口(效率机制)
关于以上的确认应答策略,对于每一个发送的数据段,都要给一个ACK确认应答,等收到ACK以后再发送下一个数据段。如下图,A花了大量时间再等待ACK,使得效率很低。
此时,为了提高效率,我们就需要缩短等待时间,此时就可以进行批量发送数据,一次发多条数据,一次等多个ACK。如下图,批量发送了4条数据,发完之后,统一等待ACK。使用一份时间,等待多个ACK,总的等待时间缩短了,整体的效率就提升了。
TCP的效率机制,让性能折损变小了,上述传输数据的过程,就成为滑动窗口。
滑动窗口,也就是批量传输。其中批量不是指无限发送,是发送到一定程度,就会等待ACK,不等待直接发送的数据是有上限的。回来一个ACK就立即发送下一条,相当于总的要批量等待的数据(窗口大小:批量等待数据的数量)是一致的。
收到一个ACK,就往后挪一个格子。
上图图解:
窗口大小指的是无需等待确认应答而可以继续发送数据的最大值。上图的窗口大小就是4000个字节(四个段)。
发送前四个段的时候,不需要等待任何ACK,直接发送;
收到第一个ACK后,滑动窗口向后移动,继续发送第五个段的数据;依次类推;
操作系统内核为了维护这个滑动窗口,需要开辟 发送缓冲区 来记录当前还有哪些数据没有应 答;只有确认应答过的数据,才能从缓冲区删掉;
窗口越大,则网络的吞吐率就越高;
滑动窗口丢包情况:
情况一:数据包已经抵达,ACK丢失。
上图就是一个严重的ACK丢失情况,但是即使是这种情况下,也不会影响到数据的可靠性传输。
丢包不会影响到数据的可靠性传输的原因:
确认序号的含义,表示该序号之前的数据已经收到了,收到了后一个ACK,就能够涵盖前一个ACK。
比如:1001这个ACK丢了,但是2001这个ACK收到了,代表这2001之前的数据收到了,所以即使1001这个ACK丢失了,也不会影响接发送方是否已经知道1~1000已经传输到接收方这个信息。 当然,如果不是中间的丢了,就会进行超时重传,直到接收到为止。
情况2:数据包直接丢失。
如上图,接收方1001~2000这个数据丢了,接收方仍然会再索要1001,不会因为收到的是2001~3000就返回3001,后面返回的确认序号,都是1001。
此时,B会向A反复索要1001这个数据,当A意识到B的反复索要,就会重传1001~2000之间的数据。
将数据重传以后,返回的是7001,而不是2001,原因是:
B有一个缓冲区,缓冲区接受了2001~7000的数据,也就是相当于B接收到了2001~7000的数据了,于是当接收到1000~2000的数据以后,B就会直接返回7001的序列号,而不是返回2001的序列号,然后接下来就会从7001开始索要后面的数据。
上述重传过程,没有任何冗余的操作,丢了数据才会进行重传,没丢的数据不必重传,整体上的传输速度是比较快的,所以称上述重传过程为快速重传。
滑动窗口,快速重传一般用于传输大量数据的时候,才会采取措施,如果只传入一两条少量且低频的操作,只会用到确认应答和超时重传。
(5)流量控制
当发送很多数据时,会用到滑动窗口,批量发送数据,需要发送的数据越多,窗口就会越大,整体的速度就会越快。
但是这并不代表速度越快越好,速度过快会影响到数据的可靠传输:
当发送方发送数据过快,可能会瞬间把接收方接收的缓冲区打满,当把缓冲区打满以后,再次发送数据,就会导致整个数据丢包。
当遇见这种情况,我们就需要引入流量控制:让接收方限制发送方的速度,保证数据的可靠性传输。
如上图,让ACK报文中,携带一个“窗口大下”的字段:当ACK为1的时候,ACK报文的窗口大小就会生效,这个窗口大小的值就是为了建议发送方发送的窗口大小。
接收方建议的窗口大小:接收缓冲区的剩余空间的大小。
如上图,初始窗口大小(接收缓冲区的剩余空间):3000
然后A会根据3000这个窗口大小,进行批量的数据传输,一直到窗口大小变为0,说明接收缓冲区满了。
当缓冲区满了以后,发送方就会暂时暂停发送,但是仍然会每隔一段时间触发一个窗口探测报文。
当窗口探测报文探测到缓冲区的数据不为0以后,就会腾出空间(应用程序会从socket中读数据,会消费缓冲区中的内容,会腾出空间),此时A就可以继续发送后续的数据了。
以上只是一个基于流量控制的简化模型,里面的窗口大小其实不是实际的窗口大小,其中还与拥塞有关,拥塞控制后面会介绍到。
(6) 拥塞控制
前面提到,滑动窗口的大小取决于流量控制和拥塞控制。
流量控制衡量了接收方的处理能力。
拥塞控制衡量了传输路径的处理能力。
如上图,如果中间有一个环节除了问题,就会影响到整个传输的过程。
为了避免这种问题,就引入了拥塞控制:衡量中间节点的传输能力。
拥塞控制机制实现:通过实验的方式,找到一个合适的发送速率。在最初的时候,发送方按照一个小的速率发送,如果不丢包,就可以提高速率;如果发现丢包了,就把速率调小。
滑动窗口的窗口大小 = min(拥塞窗口,流控窗口)
如上图,
发送开始时,拥塞窗口大小为1;
每次收到一个ACK应答,拥塞窗口+1
每次发送数据包时,将拥塞窗口和接收端主机反馈(流控窗口)的窗口大小作比较,取最小值,就是实际发送的窗口。
以下是一个拥塞窗口变换情况:(重要)
横轴:传输伦次:指第一次发送,第二次发送........
竖轴:拥塞窗口大小:准备按照多大的速率发送数据(不考虑流量控制的情况)
慢开始:刚开始传输,会给一个非常小的窗口(也就是以比较小的速率传输)
指数规律增长:每次翻倍速度传输,以指数增长,速度传输非常快,可以放窗口的大小断树间内就达到一个比较大的值,可以使得传输速度快速接近当前网络传输路径的能力瓶颈。
以上的指数增长,会使得传输速度达到一定阈值,使得传输速度变为一个很大的值,为了避免指数增长突然超过上限,就会将指数增长变为线性增长。当增长到一定程度后,出现丢包,认为当前窗口大小达到当前路径上的传输上限了,然后出现了网络拥塞。此时,就会将窗口大小打回到一个比较小的初始值,然后继续重复上述的工作。
(7)延时应答(效率机制)
延时应答也就是在发送ACK的时候不立即发送,而是等一会再发。
延时应答会提高数据传输的效率。
首先发送方发送一次数据,立即返回一个ACK,此时ACK就带有一个窗口大小,此时设这个窗口大小为n。但是,如果发送方发送方发送数据以后,接收方稍等了片刻,才返回ACK,此时的窗口大小,大概率比n大。
原因是:接收方等的这片刻,应用程序会从接收缓冲区消耗一部分数据,就会使得窗口大小变大,从而提高了数据的传输效率。
延时应答的效果,就是通过此延时,让接收方应用程序多消费点数据,使得反馈的窗口大小变大一些,从而使发送方的发送速率变快一些,使接收方处理数据也变得轻松一些。
延时应答两种策略:
-
数量限制:每隔N个包就应答一次
-
时间限制:超过最大延迟时间就应答一次。
(8)捎带应答
基于延迟应答,客户端在很多情况下,在应用层使“一发一收”的。这个时候ACK就可以搭顺风车,和response一起返回给客户端。这种情况就叫做捎带应答。
(9)面向字节流(粘包问题)
了解粘包问题需要注意的点:
粘包问题中“包”:应用层数据报。
在TCP协议中没有“报文长度”的字段,但是有序号这样的字段
站在传输层角度,TCP是一个一个报文过来的,按照序号排号放在缓冲区中
站在应用层的角度,看到的是一串连续的字节数据
粘包问题:当发送方连续给接收方发了多个应用层数据报,此时数据报记载接收方缓冲区里,仅仅挨在一起,当接收方的应用程序在读数据报时,难以区分从哪到哪时一个完整的应用层数据报,就容易读出半个包/一个半等等,这种情况就叫做粘包。解决粘包问题,我们可以定义分割符或者约定长度等等,根据实际长度取定义解决问题的方式。
(10)异常情况
以下有几种常见的异常情况。
-
进程关闭/进程崩溃
进程没有了,socket是文件,随之会被关闭,虽然进程没了,但是连接还在,仍然可以四次挥手。
-
主机关机(正常流程关机)
会先杀死所有的用户进程,也会触发四次挥手,如果四次挥手没执行完,比如还没来的及返回ACK,此时发送方就会重传FIN,重传几次之火,发现都没有ACK,就会尝试重置连接,如果还不行,就会直接释放连接了。
-
主机掉电(拔电源了)/网线断开
瞬间机器关机,来不及进行任何挥手操作
对端是指掉电方。
如果对端是发送方,就会收不到ACK -> 超时重传 -> 重置连接 -> 释放资源
如果对端是接收方,接收方就会不知道发送方因为掉电还没来的及发送新的数据还是根本就没发送。但是其实,TCP内置了心跳包(保活机制),以防这种情况带来的问题。如果对端是接收方,对端会定期给发送一个心跳包(ping),然后接收方就返回一个(pong)。如果每个ping都有及时的pong,这个时候说明对端的状态是良好的,反之,ping过去之后,没有pong,说明心跳没了,对端那边就发生了问题。
(10)异常情况
以下有几种常见的异常情况。
-
进程关闭/进程崩溃
进程没有了,socket是文件,随之会被关闭,虽然进程没了,但是连接还在,仍然可以四次挥手。
-
主机关机(正常流程关机)
会先杀死所有的用户进程,也会触发四次挥手,如果四次挥手没执行完,比如还没来的及返回ACK,此时发送方就会重传FIN,重传几次之火,发现都没有ACK,就会尝试重置连接,如果还不行,就会直接释放连接了。
-
主机掉电(拔电源了)/网线断开
瞬间机器关机,来不及进行任何挥手操作
对端是指掉电方。
如果对端是发送方,就会收不到ACK -> 超时重传 -> 重置连接 -> 释放资源
如果对端是接收方,接收方就会不知道发送方因为掉电还没来的及发送新的数据还是根本就没发送。但是其实,TCP内置了心跳包(保活机制),以防这种情况带来的问题。如果对端是接收方,对端会定期给发送一个心跳包(ping),然后接收方就返回一个(pong)。如果每个ping都有及时的pong,这个时候说明对端的状态是良好的,反之,ping过去之后,没有pong,说明心跳没了,对端那边就发生了问题。
三、TCP和UDP的差别
TCP可靠传输,效率不高,主要应用于文件传输,重要状态更新等场景。
UDP不可靠传输,效率高,主要用于对高速传输和实时性要求较高的通信领域,比如视频传输,广播等等。
两种协议怎么用,还是需要根据具体的需求场景去使用。
mron: 大佬,没太看懂因果图22、21、11代表的啥意思
张彦峰ZYF: 其他互访呀!
秋刀鱼(已过期): 博主求源码
zhenzhizz`: 求画流程图的软件
️小艺的学习旅途: 是的是15