当前位置: 首页 > 科技观察

图解说明-UDP一定比TCP快吗?

时间:2023-03-14 09:06:27 科技观察

也就是说,UDP比TCP快吗?相信即使你不是千篇一律的老手,也会下意识脱口而出:“是”。有必要问为什么,估计大家也能给出大概的思路。不过这也让人好奇,难道用UDP就一定比用TCP快吗?什么情况下UDP会比TCP慢?今天就来聊聊这个话题。使用套接字进行数据传输作为程序员,假设我们需要从计算机A的进程向计算机B的进程发送一段数据,我们在代码中一般会使用套接字进行编程。套接字就像电话或邮箱(邮政信箱)。当你要发信息、拨电话或把信息放入邮箱时,socket内核会自动完成向对方传输数据的过程。基于socket我们可以选择使用TCP或者UDP协议进行通信。对于像TCP这样的可靠性协议,每发送一条消息,你都可以清楚地知道对方是否收到了。就像打电话一样,“喂”两声就可以知道对方是否在听。而UDP就好比是寄信到邮局邮箱。你寄出的信件你不知道是否正常收到,有可能丢失。这让我想起了大约17年前。那时候,网购还没有现在这么发达。如果你想买一本杂志《掌机迷》,你必须把钱放在信封里,然后等一个月。丢失的。我至今印象深刻,因为那是我和弟弟积攒了很久的钱。..回到套接字编程的话题。创建套接字的方法如下。fd=socket(AF_INET,具体协议,0);注意上面的“具体协议”,如果传入SOCK_STREAM,是指使用字节流传输数据,说白了就是TCP协议。什么是TCP?如果传入SOCK_DGRAM,则指的是使用数据报来传输数据,即UDP协议。什么是UDP?返回的fd指的是sockethandle,可以理解为socket的ID号。通过这个fd可以找到内核中唯一的socket结构。如果想通过这个socket发送消息,只需要操作这个fd,比如执行send(fd,msg,...),内核会通过这个fd句柄找到socket,然后执行操作发送数据。如果一切顺利,此时对方执行接收消息的操作,即recv(fd,msg,...),就可以拿到你发送的消息了。Udp收发流程异常处理但是不顺利怎么办?比如消息发送到一半,丢包了怎么办?丢包的原因有很多。我在之前写的《用了TCP协议,就一定不会丢包吗?》里已经详细讨论过了,这里就不展开了。UDP和TCP的态度是不一样的。UDP说:“哦,是吗?那又怎样?关我什么事。”TCP的态度却截然相反,“啊?那不行,是不是我发的太快了?是不是链路太拥堵了,别人影响了?”怎么样?不过你放心,我一定会补发《TCP老实人石锤》的。且看这位老实人在背后默默做了些什么。重传机制对于TCP,它会在发送的报文上加上一个编号(sequence),接收方收到后会返回一个确认(ack)。发送方可以通过ack的值知道接收方收到了哪些序列包。如果长时间得不到对方的确认,TCP就会重新发送报文,也就是所谓的重传机制。TCP重传流控机制,但是重传本身对性能有严重影响,所以退而求其次。所以TCP需要考虑有没有办法尽量避免重传。因为数据发送方和接收方处理数据的能力可能不同,如果发送的数据量能根据双方的能力进行调整就好了,所以有一个发送和接收窗口,基本上就是它的作用从名字就可以看出,比如接收窗口的大小是指接收方当前可以接收的数据量,发送窗口的大小是指发送方当前可以发送的数据量。TCP根据窗口的大小来控制发送的数据量,可以大大降低丢包的概率。流量控制机制滑动窗口机制接收方收到数据后,会继续处理,处理能力不是一成不变的。有的时候处理的快一些,那么你就可以收到更多的数据,而如果处理的慢一些,你就希望对方能少一些。发送一些数据。毕竟发送太多,可能会处理不当,造成丢包,进而导致重传,这可不是什么好主意。因此,我们需要动态调整接收窗口的大小,于是就有了滑动窗口机制。看到这里,你可能会有些疑惑。流量控制和滑动窗口机制看起来很像。他们之间是什么关系?让我总结一下。实际上,现在TCP是通过滑动窗口机制来实现流量控制机制的。Slidingwindowmechanism拥塞控制机制但这还不够。有时会发生丢包,并不是因为发送方和接收方的处理能力。与网络环境有关。您可以将网络想象成一条道路。路上可能满是别人的车,只给一辆车留空位。即使你家里有5辆车,而你的目的地正好有5个停车位,你们也不可能同时一起上路。所以TCP希望能够感知外部网络环境,根据网络环境及时调整自己发送的数据包数量。比如这条路只够两辆车跑,那我就只派两辆车。但是外部环境如此复杂,TCP是如何感知的呢?TCP会先慢慢地试探性地发送数据,不断增加数据量,越来越多,先发送一个,再发送两个,四个……直到出现丢包,TCP就会知道当前网络大概能承受几个数据包。这就是所谓的拥塞控制机制。很多人会怀疑流量控制和拥塞控制的关系。我在这里简单总结一下。流量控制是针对单个连接的数据处理能力的控制,拥塞控制是针对整个网络环境的数据处理能力的控制。切分机制但是上面说的是如何降低重传的概率。看来重传是不可避免的。如果真的发生了,有什么办法可以减少它的影响吗?有。当我们需要发送一个非常大的数据包时,如果数据包丢失了,我们不得不重传同一个大数据包。但是如果我能把它分成一个小段,那它就真的丢了,那我只需要重传那个小段,就大大减轻了重传的压力。这就是TCP的分段机制。而这个所谓的短长度在传输层被称为MSS(MaximumSegmentSize)。如果数据包长度大于MSS,则分成N个小于或等于MSS的包。MSS分包,在网络层,如果数据包仍然大于MTU(MaximumTransmitUnit),则继续分包。MTU分包一般情况下,MSS=MTU-40Byte,所以TCP分片后,很有可能到了IP层就不会再分片了。MSS和MTU的区别乱序重排序机制由于数据包会被分段,链路复杂到会丢包,数据包乱序也就不足为奇了。比如发送数据包1、2、3,1号数据包经过其他网络路径,数据包2、3先到,数据包1后到,所以数据包的顺序就变成了2、3、1.TCP也考虑到了这一点。根据数据包的顺序,接收方可以知道数据包的顺序。后发的数据包先到,所以要先放入一个专门的乱序队列,等所有数据都到后,乱序队列中的数据包的顺序会重新排列,然后再发送发送给用户。这是乱序重新排序。行机制。乱序队列等待数据包的到来连接机制前面说过,UDP是无连接的,而TCP是面向连接的。这里所说的联系到底是什么?TCP通过上面提到的各种机制来实现数据的可靠性。这些机制的背后是通过每个数据结构实现的逻辑。为了实现这个逻辑,操作系统内核需要在两端的代码中维护一个复杂的状态机(三次握手、四次握手、RST、关闭等异常处理机制)。这个状态机其实就是所谓的“连接”。这其实就是TCP的连接机制,而UDP没有使用这个状态机,所以是“无连接”。网络环境中的链路很长很复杂,数据丢包很常见。我们通常使用TCP进行各种数据传输,而我们完全不知道这些东西。岁月怎能静好,是TCP为你挑起重担。这就是TCP“面向连接、可靠、基于字节流”三大特性中“可靠”的含义。如果您不相信我,请尝试使用UDP。如果你丢了一个包,那就真的丢了,让你怀疑人生。使用UDP一定比使用TCP快吗?这时候UDP就不满了:“因为我没有这些复杂的TCP可靠性机制,我速度很快。”嗯,这就是为什么大多数人认为UDP比TCP更快的原因。事实上,在大多数情况下都是如此。没有什么不妥。问题来了。是否存在使用UDP但比TCP慢的情况?其实有。在回答这个问题之前,有必要先说一下UDP的用途。其实一般人都不会尝试把裸udp直接放到生产环境做项目。UDP的价值在哪里?在我看来,UDP的存在本质上是内核提供的一种最小的网络传输功能。很多时候,虽然大家都声称使用UDP,但其实很害怕它的丢包问题,所以大多数情况下,各种层次的应用层可靠性保证都是在UDP的基础上进行的。比如农药之王使用的KCP,以及最近流行的QUIC(HTTP3.0),其实都是在UDP的基础上实现了重传逻辑,实现了一套类似于TCP的可靠数据。性机制。教科书上最喜欢提到的是UDP适用于音视频传输,因为这些场景允许丢包。但实际上并不是所有的包都能丢,比如重要的关键帧,就得重传。此外,还有一些乱序处理机制。让我举一个例子。在进行音视频通话的时候,你可能遇到过中间部分信息丢失的情况,但是乱序的情况你应该没有遇到过。比如对方给你打网络电话说:“我好想给小白点个赞!”这时候网络信号不好,可能会听到“我……喜欢看”的声音。但是我从来没有遇到过像“我在看小白所以我想点赞”这样乱七八糟的场景吧?因此,虽然选择了UDP,但一般还是在应用层实现一些重传机制。那么问题来了,如果我现在需要传输一个特别大的数据包。在TCP中,内部会根据MSS的大小进行分段。此时进入IP层后,每个数据包的大小都不会超过MTU,所以IP层一般不会进行分片。这时候就出现丢包,重传每个MSS段就可以了。TCP是分段的,但是对于UDP,是不会分段的。如果数据太大,到达IP层就会分片。如果此时出现丢包,如果再次重传,则会重传整个大数据包。UDP不分片对于以上情况,使用UDP比TCP慢。当然,解决起来并不复杂。这里的关键点在于是否实现了数据切分机制。如果使用UDP的应用层也实现了分段机制,就不会出现上述问题。总结为了实现可靠性,TCP引入了重传机制、流量控制、滑动窗口、拥塞控制、分段和乱序重排机制。虽然UDP没有实现,所以一般来说TCP比UDP慢。TCP是面向连接的协议,而UDP是无连接协议。这里的“连接”实际上是两端代码中由操作系统内核维护的一组复杂的状态机。大多数项目都会在UDP的基础上模仿TCP来实现不同程度的可靠性机制。比如农药大王使用的KCP,其实就是基于UDP在应用层实现了一套重传机制。对于UDP+重传场景,如果要传输一个大数据包,没有实现分片机制,数据会在IP层被分片。一旦丢包,需要重传整个大数据包。而TCP不需要考虑这个,它会在内部自动分片,丢包重传分片即可。在这种情况下,TCP实际上更快。