网络编程利器TCP与UDP

204 阅读11分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

TCPUDP都是传输层的协议!

什么是TCP协议

什么是TCP协议或者说它能用来干什么?

它是建立连接,可靠交付,面向字节流,有拥塞控制等安全保障,有状态服务的传输层协议!

TCP包头

image-20220402140826674

  • 源端口和目标端口:和UDP一样,因为需要知道目的地
  • 序号:解决乱序问题
  • 确认序号:解决不丢包,确认对方收到!
  • 状态位:SYN 是发起一个连接,ACK 是回复,RST 是重新连接,FIN 是结束 连接等 ,比如三次握手,四次挥手等发生网络状态变化时发送的信号。
  • 窗口大小:方便做流量和拥塞控制,标识以及声明自己的处理包的能力!

TCP的核心要素

顺序问题 ,稳重不乱; 丢包问题,承诺靠谱;

连接维护,有始有终; 流量控制,把握分寸;

拥塞控制,知进知退。

TCP协议是如何保证可靠传输的?

三次握手

最为经典的三次握手,基本现在的面试很经常会遇到!

李白:你好,我是剑仙李白!

杜甫:你好,剑仙,我是诗圣杜甫!

李白:你好,诗圣!

一般多称为请求->回答->确认回答三个回合

为什么是三次而不是两次?

因为两个人打招呼,杜甫的回答让李白知道,它知道自己是谁了。但是杜甫说完话之后,不能代表李白一定听到了,比如上面是接电话说的一段话,那李白最后不说你好,诗圣!,那么有可能李白是走开了或者电话信号不好没听到!,所以当李白回了话之后,两人互相表明身份之后,就可以正常交易了,至于杜甫还要回知道了吗?不用了,因为双方已经表明身份已经可以建立交易了,多余的确认也只是冗余了!

三次握手除了双方建立连接外,还需要确认TCP包的序号问题,从数字几开始,为什么不能默认是1呢?

因为如果发送了半天到3的地方断网了,重连三次握手之后,又是默认1开始,那就等于又开始发1,2了,这时候上次断网回来的3回来了,会被理所当然认为是重连后发的,那么自然会发生错误!

所以每个连接都要有不同的序号,且是随着时间变化!双方建立完连接后状态变化如下图:

image-20220402143017046

起初 ,客户端和服务端都处于 CLOSED 状态。先是服务端主动监听某个端口,处于 LISTEN

之后,客户端主动发起连接 SYN,之后处于 SYN-SENT 状态。服务端收到发起的连接,返回 SYN,并且 ACK 客户端的 SYN,处于 SYN-RCVD 状态。

再之后,客户端收到服务端发送的 SYN 和 ACK 之后,发送 ACK 的 ACK,之后处于 ESTABLISHED 状态

最后,服务端收到 ACK 的 ACK 之后,处于 ESTABLISHED 状态,

四次挥手

杜甫:我该说的都说了,下次再说!

李白:嗯嗯,那只好下次再说!

杜甫:好,我挂了!

李白:(听到杜甫说完)好!

互相都确认完,杜甫离场了,然后李白也离场了,成功断开了连接!如果杜甫不说好,我挂了!,那么李白就不知道杜甫有没有听到自己说的话,也不知道杜甫现在在干嘛,四次挥手很有必要!

image-20220402144056569

为什么需要四次握手?

当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。这个窗口的大小应该等于上面的第二部分加上第三部分,就是已经交代 了没做完的加上马上要交代的。超过这个窗口的,接收端做不过来,就不能发送了

发送端(老板):

image-20220402145528147

接收端(员工):

image-20220402145725306

对于接收端来讲,它的缓存里记录的内容要简单一些。
第一部分:接受并且确认过的。也就是我领导交代给我,并且我做完的。
第二部分:还没接收,但是马上就能接收的。也即是我自己的能够接受的最大工作量。
第三部分:还没接收,也没法接收的。也即超过工作量的部分,实在做不完。

一、 顺序问题与丢包问题

在发送端来看,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 的数据包丢了,这该怎么办呢?

  1. 超时重试,也即对每一个发送了,但是没有 ACK 的包,都有设一个定时器,超过 了一定的时间,就重新尝试.这个时间,根据超时遇到的次数进行增加,多次超时会将下一次设置为上一次的两倍,因为网络差不应该重试频繁,这个是自适应重传算法。
  2. 快速重传,当接收方收到一个序号大于下一个所期望的报文段时,就检测到了 数据流中的一个间格,于是发送三个冗余的 ACK,客户端收到后,就在定时器过期之前,重传 丢失的报文段。例如,接收方发现 6、8、9 都已经接收了,就是 7 没来,那肯定是丢了,于是发送三个 6 的 ACK,要求下一个是 7。客户端收到 3 个,就会发现 7 的确又丢了,不等超时,马上重发。
二、流量控制问题

image-20220402150939245

每次传包的时候会带上一个未发送的窗口,如果我们需要发送的窗口为发送未确认的5-9,那么如果4的确认来的时候,那么我们12往右移动一格13也就纳入到未发送可发送的窗口中了。

如果一口气发送完了!

image-20220402151148718那么就可以等待5的确认包回来,再进行右移窗口!

当然也可以不固定,因为接收方处理速度不一定是恒定的!,可以适当根据速度来调整我们窗口的大小!

发送方会定时发送窗口探测数据包,看是否有机会调整窗口的大小。当接收方比
较慢的时候,要防止低能窗口综合征,别空出一个字节来就赶快告诉发送方,然后马上又填满
了,可以当窗口太小的时候,不更新窗口,直到达到一定大小,或者缓冲区一半为空,才更新窗
口。
三、拥塞控制问题

TCP 发送包常被比喻为往一个水 管里面灌水,而 TCP 的拥塞控制就是在不堵塞,不丢包的情况下,尽量发挥带宽。

拥塞是通过窗口的大小来控制的,前面的滑动窗口 是怕 发送方把接收方缓存塞满,而拥塞窗口,是怕把网络塞满。

往管道里面倒水,快了容易溢出慢了浪费带宽,要摸着石头过河找到最优值,

如果我们通过漏斗往瓶子里灌水,我们就知道,不能一桶水一下子倒进去,肯定会溅出来,要一开始慢慢的倒,然后发现总能够倒进去,就可以越倒越快。这叫作慢启动。

如果速度太快就容易满,造成大面积的超时重传和包丢失!

image-20220402152104427

后来有了TCP BBR 拥塞算法。它企图找到一个平衡点,就是通过不断的 加快发送速度,将管道填满,但是不要填满中间设备的缓存,因为这样时延会增加,在这个平衡 点可以很好的达到高带宽和低时延的平衡

什么是UDP协议

它是基于数据报的,无状态服务,没有安全措施的传输层协议!

UDP包头

和TCP相比,这里包头除了满足基本通信的几个词,没有多余的注意点了!

image-20220402115304041

三大特点

  • 数据报简单,沟通成本低!
  • 不建立连接,端口在哪报文去哪!
  • 网络出现什么问题我不管,我只是带信的,丢了我不管!

为什么UDP协议快速高效?

综上所述,小伙子现在你应该知道UDP为什么很快了吧!

TCP协议和UDP协议使用场景分析

或者说TCP协议的场景和UDP协议的场景,两者协议各有适合的场景,并没有绝对的好与坏,全看项目选型!

UDP场景

  1. 需要资源少,网络较好的情况下且对丢包可容忍的应用。比如DHCP就是基于UDP协议获取IP的,获取不到没关系,后面再多试几次!
  2. 不是一对一,可以广播的应用,UDP的不连接,导致可以多播
  3. 处理快延迟低,即使网络拥塞也不怕的场景。

当然如果是能利用UDP的这些特点,再把缺点部分自己实现保障手段就再好不过了!比如丢包自己重传还有可靠保证!

直播,网页或App访问,移动通信还有实时游戏,场景:游戏对实时要求较为严格的情况下,采用自定义的可靠 UDP 协议,自定义重传策略,能够把丢 包产生的延迟降到最低,尽量减少网络问题对游戏性造成的影响

TCP场景

  1. 当对网络通信质量有要求时,比如:整个数据要准确无误的传递给对方,这往往对于一些要求可靠的应用,比如HTTP,HTTPS,FTP等传输文件的协议,POP,SMTP等邮件的传输协议。常见使用TCP协议的应用: 1.浏览器使用的:HTTP 2.FlashFXP:FTP
  2. 对数据要求完整性的,比如重要的用户数据
  3. 对时间响应效率允许有一点点延迟,但不是太多的,最主要是一致性!