1.引言

作为通信基础,在面试中经常遇到对TCP与UDP相关问题,我也经常对面试者提出该问题,问题虽然基础,但对于各个层次的人都能考量出其在通信上的理解和编码功底深浅。

谈到二者的差别,许多人张口便能回答,连接和非连接,流式和非流式,可靠与非可靠。但再深入一步,为何TCP是流式,UDP是非流式,其核心差别在什么地方?通信架构设计或关键业务场景中,到底何时该选用TCP,何时该选用UDP,在使用这两种通信方式的情况下,怎样才能发挥最高效能?这些问题,非有深入了解,愿意刨根问底,很难掌握全面。

2.从需求分析OSI模型与TCP/UDP协议

理解一个架构和方案的最佳途径莫过于分析其最原始的背景需求,让我们回归到最原始的需求——通信:

这是一个最简单的通信需求,从A将数据传到B,分析其需求领域,无非可归纳为:发端如何发,总线如何传,收端如何收,从这里我们可以总结出来至少两个大需求:需要一个收发的协定(规范一次收发多少数据,怎么收发),需要定义传输总线的规范(例如,规范网线、光纤、其他总线等的高低电平是否有统一的代指)。这里实际已经产生了传输层物理层。现在数据包中的内容只有“数据”本身。

让我们把他变得稍复杂一点:

现在通信的客户多了起来,多个节点需要相互交换数据,产生了一个核心需求:标记网络中的各个设备,为其命名,使通信过程中的各设备可以找到对应的目标。现在,我们有了网络层,传输的包也发生了变化:现在包中的内容是“地址”+“数据”。

让我们把他变得更复杂一些:

现在他更贴合我们日常实际用到的网络构型了,在这种构型中,有了更复杂的传输链路,传输过程中受到干扰,数据丢失的可能性在增大,这种复杂长链路传输的情况下,必须有一些独立的设计机制来保障两个终端之间的传输不受影响,我们需要定义帧结构、物理寻址(MAC)、差错检测(CRC),即:A的业务数据要送给交换机,某些软件层的机制保障这些业务数据正确送达交换机(定义总线上传输数据的边界),包括了将这些业务数据转化为二进制(以进一步转化为高低电平),使用某些编码技术保证受干扰后数据的纠错和还原等。OK,现在我们有了数据链路层。传输的包再次发生了变化:现在包中的内容是“帧头”+“地址”+“数据”。

3.完整的协议过程

现在我们已经保障了最基本的网络传输,让我们以现在应用最广泛的以太网通信为例,整理一下我们现在能做什么,我们可以基于网络层协议(IP协议)进行多层组网通信,实现网络路由/交换等功能,将一个终端的信息准确的送达到另一个终端。

想想我们还缺了什么?现在我们的操作系统基本都是复杂的多任务操作系统,通信需要为上层业务提供全面的底层支撑,这就要求通信需要为多应用提供服务,例如在上图中C1到A的数据和B到A的数据,甚至是C1中不同应用到A的数据都应该独立区分,所以,这里对传输层的设计提出了更进一步的要求:更细粒度的流量和传输控制。TCP/UDP协议即是为了这些更通用,更广泛的需求而设计的,其中以“端口”的概念区分了不同的传输数据流量。此时,由于传输层的协议设计,我们的数据包变成了“帧头”+“地址”+“端口”+“数据”。

此时,你也可以手动抓一抓以太网的TCP/UDP包分析对比一下,看看是不是更容易理解了。

基于以上分层设计协议的过程也就变成了:

需要说明两点:

  1. 结合TCP/UDP的设计背景和目标,其省略了会话层和表示层,这使其通用性得到加强,专用场景的适配受到限制,故其能作为更通用的底层协议,但也给类似HTTP、FTP、SSH等更上层协议的设计留下了更灵活的设计空间。
  2. TCP/UDP是基于IP协议的上层协议,其对物理层和数据链路层没有直接规范,但通过其对稳定性、延迟控制、数据单元兼容、流控等层面都提出了一系列隐形的性能需求,某些总线和配套协议无法满足要求从而存在适配兼容性问题。

4.TCP/UDP协议的本质差异

理解了上述基本的理论问题,我们再来细化理解TCP和UDP的本质差异,先来看UDP和TCP的设计目标,TCP的设计目标是为应用层提供可靠的、面向连接的字节流服务,而UDP的目标是为应用层提供极简的、无连接的尽力而为服务。

先来分析TCP,其核心是面向连接,字节流服务,面向连接实际是提供字节流服务的基础,也是可靠性的基础,我们常常听到的所谓三次握手,四次挥手就发生在这里,通过握手挥手机制创建连接,通过滑动窗口机制保障数据传输过程的流控,通过校验重传保证数据的正确性,这是传输层的核心机制。由于其面向连接,无单次传输数据上限,在传输层自动将目标传输数据分片(结合滑动窗口的拥塞控制机制和协商的MSS限制),故其在链路层不需要再分片,直接发送。

再来说UDP,其实际上是更简化的协议,通过UDP头进行UDP控制,在传输层实际没有太多工作,系统内核填写UDP头,将UDP包转交给IP层,IP层结合MTU对UDP包进行判断,若长度大于MTU限制,则分片后传输。这里需要注意的是,由于UCP协议的限制,其表示包长度的字节只有两个字节,故其单包最大长度是65535,超过此长度发送一般会失败(一般内核协议栈实现不对其进行处理)。

5.TCP与UDP的选择与应用

说清楚了二者的原理,再来谈谈具体业务中的应用。

我们其实都清楚,要可靠用TCP,要性能用UDP,但其界限到底在哪里?

具体场景要具体分析,TCP低性能的关键点在哪里?主要是在流式发送过程中的校验和重传,TCP再传输过程中将数据缓存后重新分割数据段传输,同一数据段的内容要传输无误后方能送到应用层,如果网络状况差,将导致缓冲区的拥塞,从而降低整体传输速度。这同样也是UDP高性能的点,某分片数据丢失,IP层无法完成重组,该包直接丢弃,所以其不存在缓冲区拥塞的问题,也没有复杂的控制和重传机制。

有没有兼顾的方法?有,例如腾讯的QQ使用UDP作为核心传输协议,在类似的情况下,必须对UDP进行补全,完善其协议,使其相对可靠且高效,例如在应用层实现类似TCP的分包和组包机制,借助UDP从传输层往下的高效特性,使其能够同时应用传输层的同步处理完成更高效,稳定的通信过程。

但是需要注意的是,在自定义完善UDP协议的情形下,其核心提升在于将TCP协议中的缓冲区处理从传输层移到了应用层,与应用层的处理逻辑并行,从而兼顾更多的应用场景,提升整体性能。如果忽略这一点,一味地补全UDP协议中可靠性等问题,最后无非是在重造一遍TCP的轮子罢了。

另外在业务中必须合理对照两类协议与业务的适配和结合关系,以免画蛇添足(例如在TCP协议上再做分包组包)或最后构建一个四不像的架构。

posted on 2025-07-04 12:05  我可是正经人  阅读(21)  评论(0)    收藏  举报  来源