陆陆续续面了几家公司,发现面试官问的不少问题我明明知道,可是我根本不知道怎么讲出来、讲准确,复习刷面经时看到许多问题我都默认我会然后带过,这就使得自己白白浪费了许多次面试机会,因此开始写文章记录并且用自己的话表达。
之前有看到一句很喜欢的话,分享给大家,共勉。
知识的学习在于点滴记录,坚持不懈;知识的学习要有深度和广度,不能只流于表面,坐井观天;知识要善于总结,不仅能够理解,更知道如何表达!
我的文章不会讲的很深,更多是用自己的话去总结学习的知识,如果有不同看法,欢迎评论区交流!
进入正题吧!
众所周知,TCP/UDP是属于传输层的协议,我将从下面几个方面进行探讨:
在上图之前我们先重新审视一下TCP这个协议;
首先,它位于传输层,而传输层的主要功能就是建立端口到端口的通信,那不难得到,报文结构是需要记录端口号的,即源端口
、目的端口号
;
我们再考虑一下,TCP可靠的这个特点,直观的来看就是拥有确认应答机制,那关于发送和确认的应答,我们自然可以想到用序列号(seq)
、确认应答号(ack)
来表示
接着,三次握手四次挥手过程中发起连接方和发起端开方需要发送带有一个标志位(SYN/FIN置1)的报文,自然也就有标志位;
下面我们引入报文结构
补充一下上面没讲到的:
选项
这个字段,可以为空,也可以附带别的信息,因此又首部长度来记录以上,TCP报文首部大小是20字节(选项字段为0);
UDP也是传输层协议,自然也有源端口
,目的端口号
;
UDP不像TCP那么可靠,自然就不会有流量控制、确认应答机制这些相关字段;
我相信大家在刷面经的过程中一定看到过,TCP是面向字节流,UDP是面向报文的,但具体是什么意思,又存在什么样的问题呢?
TCP是面向字节流:“字节就是字节”,也就是说对于TCP协议来说,信息没有什么特殊的,大家都是字节,因此TCP就没有边界的的概念;
如果是客户端连续发送数据,服务器端的缓冲区如果足够大,就会一次性接收过来,这就是没有边界的意思。
UDP是面向报文:客户端连续发送数据,服务器端缓冲区不论有多大,都是一次一次接受,客户端发多少次,服务器端接收多少次,这就是有边界的概念
至此!我们引出一个问题
答:粘包!当客户端连续发送数据,服务器端一次接收过来,就会造成多个包粘在一起的情况!或者某些包被分隔开与其他包粘在了一起;
答:
我们可以协定规定一个包大小是多少,不满足的部分用0等特殊字符补满。
或者人为规定结束符号例如"@ # $ %"等,只要没遇到符号,就表示没结束前一个包。
这里请读者自己想想,两者各自的特点是什么?
TCP安全,UDP快,这个不难想到;
TCP的安全我们放到下面下一个大标题去讲,这里讲一下UDP的快!
首先UDP报头短只有8字节,TCP最小都要20字节,并且UDP不需要进行三次握手四次挥手的相关操作,省去了建立连接销毁的过程,快就快在这里!
所以,如果面试官问你dns为什么要用udp协议,我想你心里已经有答案了,甚至还能给他讲一讲别的!
这里内容较多,我单独摘出来讲;
接收方在确认应答时,会将发送的seq序号+1作为ACK返回
如果发送方发 1 2 3 4,2包丢了,1 3 4顺利到达,接收方仍会返回ACK为2的报文(意思是给我2我没2)
数据发送出去丢了怎么办!
TCP维护了一个超时重传计时器,在数据发出去后就开始计时,时间到了还没有收到确认应答,就会重新发送这个数据。
记得我们之前分析TCP报头结构时候有一个窗口的字段吗?没错他就是搞这个的;
接收端数据处理能力是有限的,如果发的太快,就会积攒到接收端的缓冲区,这时候继续发那不就溢出来了?(怎么突然想到紫薇尔康)
因此维护了一个字段用于接收方向发送方传递信息,你就传xxx这么多就行了,多了我要不了;
多说一句,那缓冲区满了咋办?当然是将窗口值写0,发送方就不发了;
那再多说一句,不让发了就下班了?其实并不是,发送方定期会发送一个数据,用于探测对方的窗口大小。
这个问题面试官问到了!心里清楚,根本不知道怎么讲!
我们思路回到刚才确认应答机制,每发送一个需要等待一个ack才能发下一次,这其中有什么缺点,应该不用我多少了吧?
滑动窗口就是让发送端无需等待确认应答就可以进行下一次发送!
那上面这个图跟窗口有啥关系啊?我们们慢慢讲;
我们先要明确窗口大小的含义:即无需确认就可以继续发送数据的最大值;
发送完1 2 3 4后收到确认应答就继续发送5 6 7 8,窗口从包含1 2 3 4滑到了包含5 6 7 8;是不是有点眉目了?
那这里存在一个问题,前面有包在发送期间丢了怎么办?
注意!只有确认应答过的数据才会从 发送缓冲区 删除掉,不然滑动窗口左侧就会卡在这里不向右滑。比如:发送1 2 3 4 时 2丢了,确认1时ack是2(表示我要2),接受到3 4还是会返回索要2的ack;
这里有个细节,就是发送端接收到值2的ack时,代表第一个包收到了,滑动窗口就会右移一格;
注意上面说的是发送期间
在发送方发送1 2 3 4后等待应答的过程中,服务器端会返回值为2 3 4 5的ACK,这时候如果其中的3丢了,有影响吗?
答案是没有影响,既然它能收到值为5的ack,自然说明前面都接收到了!
这个窗口的大小谁来指定呢?
答:TCP报头结构里的窗口字段(和流量控制结合起来了),发送方缓存的数据维护如下
可用窗口就是应答报文的窗口大小;
大概过程大家可以再结合下面的图理解
如果图片还不能够让你搞懂原理,可以用下面的工具进行模拟,开箱即用哦!滑动窗口模拟器
这个就是大头了!
RTT:报文 发送出去+应答接受回来 的一小段时间
拥塞窗口:这是一个根据网络状态会变化的量,先知道这里即可。
阈值:一个界限,界限前后调用不同算法;
四大算法:
一开始使拥塞窗口为1去探测网络状态,每次接收到一个ACK就会+1;
即在一个RTT时间内,拥塞窗口大小成指数增长,你品品;
慢启动以后窗口大小指数增长,那什么时候转换策略呢?
对咯,是到阈值就会转变策略,会变成线性增长;
当我们发送一系列的报文比如有1 2 3 4,1在发送过程中丢掉了,2 3 4顺利到达,那么就会返回3个值为2的ACK,(注意这时网络是ok的,报文的发送返回是很快的 在一个RTT时间内,还不至于让超时重传机制计入),发送端就会立刻重传2的的报文;
那快速重传后 拥塞窗口继续线程增长?
NoNoNo!正确操作是,发生快速重传后,阈值就设为 拥塞窗口的一半,窗口也等于自身的一半,然后继续开始线性增长探测网络情况;
如果是超时重传怎么恢复?
答:阈值设为拥塞窗口的一半,拥塞窗口设1,然后重新开始慢启动;
关于个人理解的滑动窗口和拥塞窗口
他们都是在发送端维护的窗口,只不过滑动窗口的大小是由接收端控制的,这一点是要好好再思考思考;
其次总不能应答报文说要多少就是多少吧?因此引入了拥塞窗口,去快快+慢慢增长去探测网络状况。
看到这里在返回滑动窗口拥塞窗口再看看,就会有一个比较深的理解了,如果还不明白,欢迎评论区探讨!
如果这篇文章有帮助到你希望留下一个赞,文中如果有不对的地方也欢迎大佬指出!