本文已参与「新人创作礼」活动,一起开启掘金创作之路。
TCP和UDP都是传输层的协议!
什么是TCP协议
什么是TCP协议或者说它能用来干什么?
它是建立连接,可靠交付,面向字节流,有拥塞控制等安全保障,有状态服务的传输层协议!
TCP包头
- 源端口和目标端口:和
UDP一样,因为需要知道目的地 - 序号:解决乱序问题
- 确认序号:解决不丢包,确认对方收到!
- 状态位:SYN 是发起一个连接,ACK 是回复,RST 是重新连接,FIN 是结束 连接等 ,比如三次握手,四次挥手等发生网络状态变化时发送的信号。
- 窗口大小:方便做流量和拥塞控制,标识以及声明自己的处理包的能力!
TCP的核心要素
顺序问题 ,稳重不乱; 丢包问题,承诺靠谱;
连接维护,有始有终; 流量控制,把握分寸;
拥塞控制,知进知退。
TCP协议是如何保证可靠传输的?
三次握手
最为经典的三次握手,基本现在的面试很经常会遇到!
李白:你好,我是剑仙李白!
杜甫:你好,剑仙,我是诗圣杜甫!
李白:你好,诗圣!
一般多称为请求->回答->确认回答三个回合
为什么是三次而不是两次?
因为两个人打招呼,杜甫的回答让李白知道,它知道自己是谁了。但是杜甫说完话之后,不能代表李白一定听到了,比如上面是接电话说的一段话,那李白最后不说你好,诗圣!,那么有可能李白是走开了或者电话信号不好没听到!,所以当李白回了话之后,两人互相表明身份之后,就可以正常交易了,至于杜甫还要回知道了吗?不用了,因为双方已经表明身份已经可以建立交易了,多余的确认也只是冗余了!
三次握手除了双方建立连接外,还需要确认TCP包的序号问题,从数字几开始,为什么不能默认是1呢?
因为如果发送了半天到3的地方断网了,重连三次握手之后,又是默认1开始,那就等于又开始发1,2了,这时候上次断网回来的3回来了,会被理所当然认为是重连后发的,那么自然会发生错误!
所以每个连接都要有不同的序号,且是随着时间变化!双方建立完连接后状态变化如下图:
起初 ,客户端和服务端都处于 CLOSED 状态。先是服务端主动监听某个端口,处于 LISTEN
之后,客户端主动发起连接 SYN,之后处于 SYN-SENT 状态。服务端收到发起的连接,返回 SYN,并且 ACK 客户端的 SYN,处于 SYN-RCVD 状态。
再之后,客户端收到服务端发送的 SYN 和 ACK 之后,发送 ACK 的 ACK,之后处于 ESTABLISHED 状态
最后,服务端收到 ACK 的 ACK 之后,处于 ESTABLISHED 状态,
四次挥手
杜甫:我该说的都说了,下次再说!
李白:嗯嗯,那只好下次再说!
杜甫:好,我挂了!
李白:(听到杜甫说完)好!
互相都确认完,杜甫离场了,然后李白也离场了,成功断开了连接!如果杜甫不说好,我挂了!,那么李白就不知道杜甫有没有听到自己说的话,也不知道杜甫现在在干嘛,四次挥手很有必要!
为什么需要四次握手?
当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。
Client端此时处于FIN-WAIT等Server再次发送FIN,故需要四步握手。
为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假象网络是不可靠的,有可以最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。
TCP的四大问题
为了保证顺序性,每一个包都有一个 ID。在建立连接的时 候,会商定起始的 ID 是什么,然后按照 ID 一个个发送。为了保证不丢包,对于发送的包都要 进行应答,但是这个应答也不是一个一个来的,而是会应答某个之前的 ID,表示都收到了,这 种模式称为累计确认或者累计应答。
为了记录所有发送的包和接收的包,TCP 也需要发送端和接收端分别都有缓存来保存这些记 录。发送端的缓存里是按照包的 ID 一个个排列,根据处理的情况分成四个部分
第一部分:发送了并且已经确认的
第二部分:发送了并且尚未确认的
第三部分:没有发送,但是已经等待发送的
第四部分:没有发送,并且暂时还不会发送的
到底能处理多少包呢?
TCP 里,接收端会给发送端报一个窗口的大小,叫 Advertised window。这个窗口的大小应该等于上面的第二部分加上第三部分,就是已经交代 了没做完的加上马上要交代的。超过这个窗口的,接收端做不过来,就不能发送了
发送端(老板):
接收端(员工):
对于接收端来讲,它的缓存里记录的内容要简单一些。
第一部分:接受并且确认过的。也就是我领导交代给我,并且我做完的。
第二部分:还没接收,但是马上就能接收的。也即是我自己的能够接受的最大工作量。
第三部分:还没接收,也没法接收的。也即超过工作量的部分,实在做不完。
一、 顺序问题与丢包问题
在发送端来看,1、2、3 已经发送并确认;4、5、6、7、8、9 都是发送了还没 确认;10、11、12 是还没发出的;13、14、15 是接收方没有空间,不准备发的。
在接收端来看,1、2、3、4、5 是已经完成 ACK,但是没读取的;6、7 是等待接收的;8、9 是已经接收,但是没有 ACK 的。
发送端和接收端当前的状态如下:
1、2、3 没有问题,双方达成了一致。
4、5 接收方说 ACK 了,但是发送方还没收到,有可能丢了,有可能在路上。
6、7、8、9 肯定都发了,但是 8、9 已经到了,但是 6、7 没到,出现了乱序,缓存着但是 没办法 ACK。
假设 4 的确认到了,不幸的是,5 的 ACK 丢了,6、7 的数据包丢了,这该怎么办呢?
- 超时重试,也即对每一个发送了,但是没有 ACK 的包,都有设一个定时器,超过 了一定的时间,就重新尝试.这个时间,根据超时遇到的次数进行增加,多次超时会将下一次设置为上一次的两倍,因为网络差不应该重试频繁,这个是自适应重传算法。
- 快速重传,当接收方收到一个序号大于下一个所期望的报文段时,就检测到了 数据流中的一个间格,于是发送三个冗余的 ACK,客户端收到后,就在定时器过期之前,重传 丢失的报文段。例如,接收方发现 6、8、9 都已经接收了,就是 7 没来,那肯定是丢了,于是发送三个 6 的 ACK,要求下一个是 7。客户端收到 3 个,就会发现 7 的确又丢了,不等超时,马上重发。
二、流量控制问题
每次传包的时候会带上一个未发送的窗口,如果我们需要发送的窗口为发送未确认的5-9,那么如果4的确认来的时候,那么我们12往右移动一格13也就纳入到未发送可发送的窗口中了。
如果一口气发送完了!
那么就可以等待5的确认包回来,再进行右移窗口!
当然也可以不固定,因为接收方处理速度不一定是恒定的!,可以适当根据速度来调整我们窗口的大小!
发送方会定时发送窗口探测数据包,看是否有机会调整窗口的大小。当接收方比
较慢的时候,要防止低能窗口综合征,别空出一个字节来就赶快告诉发送方,然后马上又填满
了,可以当窗口太小的时候,不更新窗口,直到达到一定大小,或者缓冲区一半为空,才更新窗
口。
三、拥塞控制问题
TCP 发送包常被比喻为往一个水 管里面灌水,而 TCP 的拥塞控制就是在不堵塞,不丢包的情况下,尽量发挥带宽。
拥塞是通过窗口的大小来控制的,前面的滑动窗口 是怕 发送方把接收方缓存塞满,而拥塞窗口,是怕把网络塞满。
往管道里面倒水,快了容易溢出慢了浪费带宽,要摸着石头过河找到最优值,
如果我们通过漏斗往瓶子里灌水,我们就知道,不能一桶水一下子倒进去,肯定会溅出来,要一开始慢慢的倒,然后发现总能够倒进去,就可以越倒越快。这叫作慢启动。
如果速度太快就容易满,造成大面积的超时重传和包丢失!
后来有了TCP BBR 拥塞算法。它企图找到一个平衡点,就是通过不断的 加快发送速度,将管道填满,但是不要填满中间设备的缓存,因为这样时延会增加,在这个平衡 点可以很好的达到高带宽和低时延的平衡
什么是UDP协议
它是基于数据报的,无状态服务,没有安全措施的传输层协议!
UDP包头
和TCP相比,这里包头除了满足基本通信的几个词,没有多余的注意点了!
三大特点
- 数据报简单,沟通成本低!
- 不建立连接,端口在哪报文去哪!
- 网络出现什么问题我不管,我只是带信的,丢了我不管!
为什么UDP协议快速高效?
综上所述,小伙子现在你应该知道UDP为什么很快了吧!
TCP协议和UDP协议使用场景分析
或者说TCP协议的场景和UDP协议的场景,两者协议各有适合的场景,并没有绝对的好与坏,全看项目选型!
UDP场景
- 需要资源少,网络较好的情况下且对丢包可容忍的应用。比如DHCP就是基于
UDP协议获取IP的,获取不到没关系,后面再多试几次! - 不是一对一,可以广播的应用,
UDP的不连接,导致可以多播 - 处理快延迟低,即使网络拥塞也不怕的场景。
当然如果是能利用UDP的这些特点,再把缺点部分自己实现保障手段就再好不过了!比如丢包自己重传还有可靠保证!
直播,网页或App访问,移动通信还有实时游戏,场景:游戏对实时要求较为严格的情况下,采用自定义的可靠 UDP 协议,自定义重传策略,能够把丢 包产生的延迟降到最低,尽量减少网络问题对游戏性造成的影响
TCP场景
- 当对网络通信质量有要求时,比如:整个数据要准确无误的传递给对方,这往往对于一些要求可靠的应用,比如HTTP,HTTPS,FTP等传输文件的协议,POP,SMTP等邮件的传输协议。常见使用TCP协议的应用: 1.浏览器使用的:HTTP 2.FlashFXP:FTP
- 对数据要求完整性的,比如重要的用户数据
- 对时间响应效率允许有一点点延迟,但不是太多的,最主要是一致性!