解读TCP协议和UDP协议的区别

本节将详细的解释一下TCP协议和UDP协议的区别,作为我的专栏《计算机网络协议快速入门教程》中的一节。

写在前面

在早期制定协议的时候,无论是哪一种的模型,传输层的定位是用来控制数据的传输。因此对于有明确的划分的层次模型,TCP和UDP的对比往往是传输层能力的对比,诸如可靠性,有无连接,有无顺序等等。但是随着技术的演进,数据传输的控制不一定只限制在传输层内,Google也基于UDP的实现了quic协议,由quic协议保证传输数据的可靠性。这样一来即使UDP本身不可靠,但是传输层之上依然可以保证可靠性。很多人会疑惑TCP是比UDP可靠,但是基于UDP的QUIC依然可靠,这是怎么回事。这是因为通常意义上对比TCP和UDP是传输层本身,需要把范围限定在传输层之内。同时可以看到技术的演进也在不断打破原有的一些观念,如果不是因为TCP/UDP的应用太过于广泛,完全替换不是那么容易,也许演进早已经更加的猛烈和彻底。同时早期的公有协议有限,一些应用不会定制应用层协议,直接基于TCP或者UDP实现,这也是大家为什么执着于对传输层的对比面。本文将依然在传输层的范围内进行TCP和UDP区别的讨论。

在面试过程中,关于计算机网络最常见的面试就是,简述下TCP和UDP的区别。通常一些答案如下:

  • TCP是有连接的,UDP是无连接的
  • TCP是可靠的,UDP是不可靠的
  • TCP是基于流传输,UDP是基于数据包传输
  • TCP是有状态的,UDP是无状态的
  • TCP是有序的,UDP是无序的

本文将从TCP和UDP的每个字段入手,对这些区别进行深入。

有连接VS无连接

TCP是有链接的,具体的表现就是,在每次正式数据交换之前,需要通过三次的握手来确定通信的双方是否准备就绪,如图1:
在这里插入图片描述
图1

在图1中可以看到,通信双方通过SYN标志位,以及对SYN包的ACK确认来完成通信双方状态的交换,只有三次握手通过,后续的数据交换才能正常的继续。

除此之外,图1的三次握手过程中,还交换了window窗口大小,MSS的大小等信息。window窗口大小用以通知通信的一方当前能够接受的数据大小,MSS大小表示TCP每次传输允许上层最大数据大小。通过这些信息的交换,通信双方能够很快的了解彼此的状态,从而为是否能够发送数据,发送多少数据,能否通信提供依据。例如当window为0的时候就不适合在进行数据的传输,而是应该等待window状态更新之后再通信。

既然有连接的建立,那必然有连接的断开,如图2为TCP断开连接的过程:
在这里插入图片描述
图2

可以看到在一条流上,当不需要数据传输的时候,可以由连接的一方发起连接断开的,经过双方协商一致之后,该条流上的通信信息会在双方进行释放。

TCP的有连接体现在连接需要建立以及连接需要释放,UDP 协议中没有对应的字段确保连接的建立,因此UDP的通信是无连接。可以看到,连接建立和释放是双方在通信参数上的协商,有连接从一定程度上也可以反应TCP是可靠的。

可靠VS不可靠

TCP传输是可靠的,UDP传输是不可靠的,可以从如下几个方面来理解:

  • 网络传输出现丢包了
  • 网络传输出现重传
  • 网络传输出现乱序
  • 对方突然下线

1,TCP通过确认序列号表示接收方收到的数据包内容,因此当出现丢包的情况,接收方不会对该数据包进行确认,会触发TCP的超时重传机制保证数据包不会被丢弃。UDP则没有对应的机制保证数据包可靠的到达接收方,因此UDP是不可靠的

2,多个数据包到达接收方之后,接收方根据TCP的序列号能够保证数据正确的重组,不会出现乱序。UDP则只能够依靠接收的顺序对应用层数据进行重组。而数据被接收的顺序和数据发送的顺序并不是总保持一致。因此TCP和UDP的有序无序也可归为可靠这一类别。UDP没有该功能,因此UDP是不可靠的。

3,当接收方收到两个一模一样的数据包的时候,TCP会根据序列号对重传的数据包进行丢弃。而UDP没有该机制,因此UDP是不可靠的。

4,接收方处理能力有限,TCP通过window和window scale字段通知发送方当前接收方的接收能力,发送方根据该大小确定发送的内容大小。UDP没有对应的机制保证发送的数据不会超过接受的能力,因此UDP是不可靠

5,当接收方突然下线,其机制和丢包是一样的。收不到接收方的确认,触发重传,达到重传次数之后,直接reset断开连接。UDP无法感知对方状态,发送方会一直的传输数据,因此UDP是不可靠的。

需要注意的是TCP和UDP的可靠指的是传输层是否可靠,该层是否能够面向上层提供可靠的服务。就像文章开头提到的,虽然UDP本身不可靠,但是基于UDP传输的服务可以把可靠的传输建立在UDP上层,例如quic协议是基于UDP,其传输的可靠性是由quic协议实现。

基于流VS基于包

通常说UDP是基于数据包传输,而TCP是基于流传输的。由于UDP有字段明确表明本次传输的数据大小,如图3:
在这里插入图片描述
图3
其蕴含的意义就是接收方在收到该数据包之后会直接根据长度交由应用层处理。同样的对于发送方来说,应用层交给传输层数据是多少,UDP则会将这些数据形成一个包进行发送,超过物理层的限制,则会在IP进行分片传输。因此往往使用UDP协议的时候,应用层往往会限制每次传输数据的大小例如512个字节,进行多次的UDP调用。

对于TCP来说,在处理应用层数据的时候,发送方每次不会将应用层数据作为一个包直接传输,会根据MSS以及对方window的大小,将一块数据分成多条数据进行传输。就行水流一样,源源不断的传送给接收方。对于接收方来说,在收到数据后,会将其存在接收缓冲区中。TCP长度表示的是头部的大小,没有指明应用层数据大小,因此接收方并不知道发送方数据有没有发送完。因此什么时候交由应用层处理,常见的是两种情况:1,缓冲区满了需要刷新数据;2,发送方发送push字段要求应用层处理数据。虽然不知道传输的数据整体有多大,但是TCP首先保证了传输的可靠性,接收方只要按照策略定期从缓冲区读取数据即可,这样数据流就是源源不断的。往往使用TCP协议的时候,应用层不会限制每次传输数据的大小,而由传输层处理,进行一次的TCP调用。

正是由于TCP这种流式传输的特点,在一些场景下会发生粘包的现象,如下:

  • tcp为了提高数据的传输效率,将应用层交下来的几个小的包合并发送,这样只需要发送一次,接收方也之需要确认一次就可以了。
  • 即使几个较小的包分开发送,在接收端也可以会在缓冲区合并,接收方也之需要确认一次就可以了。
    这会导致接受方无法将这几个合并的包拆开来,因此就发生了粘包。因为在一些游戏中,这几个小报文可能代表不同的指令,因此必须区分开来,不然后续指令无法生效。解决粘包场景问题的方法就是在应用层加上数据长度字段进行区分,比如http的content-length字段等等。因此可以看到,这种现象必须依赖应用层的功能,对于直接基于TCP的应用来说是不可行的,需要定制应用层的协议。由于Udp是包传输,因此udp是不会发生粘包问题的。

效率

  • TCP首部的长度范围是20-60个字节,UDP的长度为8个字节,因此UDP的效率高。
  • TCP为了保持连接的有效性,需要额外的三次握手和四次挥手,需要额外的开销。
  • TCP需要等待对方确认之后,才会传输后续的数据,因此速度依赖于对方的确认速度。而UDP没有该机制,某情况下效率高。
  • TCP需要维护传输的状态参数,例如当前状态,TCP重组信息,窗口大小等等,因此TCP的进程会占用更多的资源。

以上就是TCP和UDP主要的一些区别。还是文章开头的观点,技术的演进会不断打破原有的一些观念,也许将来TCP和UDP的区别不是那么重要,UDP缺少的功能可以在更高的一层进行实现,多个协议层的融合也未可知。

本文为CSDN村中少年原创文章,未经允许不得转载,博主链接这里

猜你喜欢

转载自blog.csdn.net/javajiawei/article/details/125946316