udp协议:udp和tcp相比快在哪里?

2022-06-22 15:47:10 浏览数 (1)

TCP 协议,是一个支持可靠性的协议。UDP 协议,是一个不支持可靠性的协议。

校验和(Checksum) 最简单的校验和算法:纵向冗余检查

UDP 不支持可靠性,但是像校验和(Checksum)这一类最基本的数据校验,它还是支持的。

不支持可靠性,并不意味着完全放弃可靠性。TCP 和 UDP 都支持最基本的校验和算法。

对于 TCP 和 UDP,都实现了校验和算法,但二者的区别是,TCP 如果发现校验核对不上,也就是数据损坏,会主动丢失这个封包并且重发。而 UDP 什么都不会处理,UDP 把处理的权利交给使用它的程序员。

最简单的校验和算法:纵向冗余检查

三次握手的原因 “已失效的连接请求报文段” 的产生在这样一种情况下:client 发出的第一个连接请求报文段并没有丢失,而是在某个网络结点长时间的滞留了,以致延误到连接释放以后的某个时间才到达 server。本来这是一个早已失效的报文段。但 server 收到此失效的连接请求报文段后,就误认为是 client 再次发出的一个新的连接请求。于是就向 client 发出确认报文段,同意建立连接。假设不采用 “三次握手”,那么只要 server 发出确认,新的连接就建立了。由于现在 client 并没有发出建立连接的请求,因此不会理睬 server 的确认,也不会向 server 发送数据。但 server 却以为新的运输连接已经建立,并一直等待 client 发来数据。这样,server 的很多资源就白白浪费掉了。采用 “三次握手” 的办法可以防止上述现象发生。例如刚才那种情况,client 不会向 server 的确认发出确认。server 由于收不到确认,就知道 client 并没有要求建立连接。”

tcp为什么具有可靠性 TCP 的可靠连接是靠 seq( sequence numbers 序列号)来达成的。 通过TCP 连接发送的每一个包,都有一个sequence number。而因为每个包都是有序列号的,所以都能被确认收到这些包。确认机制是累计的,所以一个对sequence number X 的确认,意味着 X 序列号之前(不包括 X) 包都是被确认接收到的。

TCP 协议是不限制一个特定的连接(两端 socket 一样)被重复使用的。

所以这样就有一个问题:这条连接突然断开重连后,TCP 怎么样识别之前旧链接重发的包?——这就需要独一无二的 ISN(初始序列号)机制。

当一个新连接建立时,初始序列号( initial sequence number ISN)生成器会生成一个新的32位的 ISN。

这个生成器会用一个32位长的时钟,差不多4µs 增长一次,因此 ISN 会在大约 4.55 小时循环一次。

而一个段在网络中并不会比最大分段寿命(Maximum Segment Lifetime (MSL) ,默认使用2分钟)长,MSL 比4.55小时要短,所以我们可以认为 ISN 会是唯一的。

三次握手(A three way handshake)是必须的, 因为 sequence numbers(序列号)没有绑定到整个网络的全局时钟(全部统一使用一个时钟,就可以确定这个包是不是延迟到的)以及 TCPs 可能有不同的机制来选择 ISN(初始序列号)。

一个 seq 过来了,跟现在记住的 seq 不一样,我怎么知道他是上条延迟的,还是上上条延迟的呢?

TCP 传递信息可以理解为美国与中国用货船来传货物,但因为一首轮船穿放不下,货物要分开一只只轮船来发货。所以需要一个序列号来识别该货物是第几个,以便到达后将其拼接回原来的货物。因为同一条航道(也就是 tcp连接)上,可能会有多批货物发送(复用 tcp 连接)。发货时,双方需要通知对方这个序列号是从哪里开始(init seq)的,这样才能辨识过来的是不是一个对的货物,以及能拼接成完整的货物。

代码语言:javascript复制
TCP A                                                TCP B
​
  1.  CLOSED                                               LISTEN
​
  2.  SYN-SENT    --> <SEQ=100><CTL=SYN>               --> SYN-RECEIVED
​
  3.  ESTABLISHED <-- <SEQ=300><ACK=101><CTL=SYN,ACK>  <-- SYN-RECEIVED
​
  4.  ESTABLISHED --> <SEQ=101><ACK=301><CTL=ACK>       --> ESTABLISHED
​
  5.  ESTABLISHED --> <SEQ=101><ACK=301><CTL=ACK><DATA> --> ESTABLISHED
​
          Basic 3-Way Handshake for Connection Synchronization
​
                                Figure 7.

第二行中, A 发送了 SEQ 100,标志位是 SYN;第三行,B 发回了 ACK 101 与 SEQ 300,标志位是 SYN 与 ACK(两个过程合并了)。注意,ACK 是101意味着,B 希望接收到 101序列号开始的数据段。第四行,A 返回了空的数据,SEQ 101, ACK 301,标志位为 ACK。至此,双方的开始 SEQ (也就是 ISN)号100与300都被确认接收到了。第五行,开始正式发送数据包,注意的是 ACK 依旧是第四行的301,因为没有需要 ACK 的 SYN 了(第四行已经 ACK 完)。

三次握手的原则设计是防止旧复用链接的初始化导致问题,为了解决此问题,我们设计了reset这个特别的控制信号来处理。

代码语言:javascript复制
作者:山尽
链接:https://www.zhihu.com/question/24853633/answer/573627478
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

TCP A                                                TCP B
​
  1.  CLOSED                                               LISTEN
​
  2.  SYN-SENT    --> <SEQ=100><CTL=SYN>               ...
​
  3.  (duplicate) ... <SEQ=90><CTL=SYN>               --> SYN-RECEIVED
​
  4.  SYN-SENT    <-- <SEQ=300><ACK=91><CTL=SYN,ACK>  <-- SYN-RECEIVED
​
  5.  SYN-SENT    --> <SEQ=91><CTL=RST>               --> LISTEN
  
​
  6.              ... <SEQ=100><CTL=SYN>               --> SYN-RECEIVED
​
  7.  SYN-SENT    <-- <SEQ=400><ACK=101><CTL=SYN,ACK>  <-- SYN-RECEIVED
​
  8.  ESTABLISHED --> <SEQ=101><ACK=401><CTL=ACK>      --> ESTABLISHED
​
                    Recovery from Old Duplicate SYN

3中,一个旧的重复的 SYN到达 B。 4中, B分别不出是否旧的,照样子正常回包。 5中,A检测到 B 返回的ACK不正确,所以返回 RST(reset) 6中,B接收到 RST(reset)信号,于是变成 LISTEN 状态。 7中,新连接正常的 SYN终于到达了,三次握手正常进行。这种是简化的情况,但是可以看出 TCP 是如何处理复用旧链接的包到达的。

请求/应答/连接模型 TCP 实现了请求、响应和连接的模型,UDP 没有实现这个模型。

连接 连接的目的是让连接的双方达成默契,倾尽资源,给对方最快的响应。

连接也是一个很好的编程模型。当连接不稳定的时候,可以中断连接后再重新连接。这种模式极大地增加了两个应用之间的数据传输的可靠性。

封包排序 可靠性有一个最基本的要求是数据有序发出、无序传输,并且有序组合。TCP 协议保证了这种可靠性,UDP 则没有保证。

在 TCP 中叫作一个TCP Segment。在 UDP 中叫作一个UDP Datagram。Datagram 单词的含义是数据传输的最小单位。在到达目的地之后,尽管所有的数据分块可能是乱序到达的,但为了保证可靠性,乱序到达的数据又需要被重新排序,恢复到原有数据的顺序。

TCP 利用了滑动窗口、快速重传等算法,保证了数据的顺序。而 UDP,仅仅是为每个 Datagram 标注了序号,并没有帮助应用程序进行数据的排序,这也是 TCP 和 UDP 在保证可靠性上一个非常重要的区别。

我们先来看一道面试题:如果客户端和服务器之间的单程平均延迟是 30 毫秒,那么客户端 Ping 服务端需要多少毫秒?

【分析】这个问题最核心的点是需要思考 Ping 服务应该由 TCP 实现还是 UDP 实现?请你思考:Ping 需不需要保持连接呢?答案是不需要,Ping 服务器的时候把数据发送过去即可,并不需要特地建立一个连接。

请你再思考,Ping 需不需要保证可靠性呢?答案依然是不需要,如果发生了丢包, Ping 将丢包计入丢包率即可。所以从这个角度来看,Ping 使用 UDP 即可。

所以这道面试题应该是 Round Trip 最快需要在 60 毫秒左右。一个来回的时间,我们也通常称为 Round Trip 时间。

通过分析上面的例子,我想告诉你,TCP 和 UDP 的使用场景是不同的。TCP 适用于需要可靠性,需要连接的场景。UDP 因为足够简单,只对数据进行简单加工处理,就调用底层的网络层(IP 协议)传输数据去了。因此 UDP 更适合对可靠性要求不高的场景。

另外很多需要定制化的场景,非常需要 UDP。以 HTTP 协议为例,在早期的 HTTP 协议的设计当中就选择了 TCP 协议。因为在 HTTP 的设计当中,请求和返回都是需要可靠性的。但是随着 HTTP 协议的发展,到了 HTTP 3.0 的时候,就开始基于 UDP 进行传输。这是因为,在 HTTP 3.0 协议当中,在 UDP 之上有另一个QUIC 协议在负责可靠性。UDP 足够简单,在其上构建自己的协议就很方便。

你可以再思考一个问题:文件上传应该用 TCP 还是 UDP 呢?乍一看肯定是 TCP 协议,因为文件上传当然需要可靠性,防止数据损坏。但是如果你愿意在 UDP 上去实现一套专门上传文件的可靠性协议,性能是可以超越 TCP 协议的。因为你只需要解决文件上传一种需求,不用像 TCP 协议那样解决通用需求。

所以时至今日,到底什么情况应该用 TCP,什么情况用 UDP?这个问题边界的确在模糊化。总体来说,需要可靠性,且不希望花太多心思在网络协议的研发上,就使用 TCP 协议。

那么通过这一讲的学习,你现在可以尝试来回答本讲关联的面试题目:UDP 比 TCP 快在哪里?

使用 UDP 传输数据,不用建立连接,数据直接丢过去即可。至于接收方,有没有在监听?会不会接收?那就是接收方的事情了。 UDP 甚至不考虑数据的可靠性。至于发送双方会不会基于 UDP 再去定制研发可靠性协议,那就是开发者的事情了。所以 UDP 快在哪里?UDP 快在它足够简单。因为足够简单,所以 UDP 对计算性能、对网络占用都是比 TCP 少的。

0 人点赞