首页>网络>正文

TCP与UDP怎么选:字节流、数据报和五个常见误区

Feng 14 阅读 网络

TCP把可靠性做进传输层,UDP把控制权留给应用层。可靠和快不是二选一,工程上的问题是:这段数据丢了要不要补,补的代价能不能接受。

为什么TCP之外还需要UDP

入门材料常说TCP可靠、UDP不可靠。这句话没错,但漏掉了另一半:网络不只需要可靠,还要低延迟、少开销、简单、可控、实时。

换个说法更准确。TCP把可靠性内置在传输层,UDP把选择权交给应用层。TCP像保价签收的快递,环节多但稳;UDP像现场喊话,不保证每个人都听清,但快。

TCP在传输层替你做了哪些事

TCP面向连接,正式传数据前要三次握手。它要保证的东西不少:数据不丢、乱序重排、重复去重、流量控制、拥塞控制。

这些能力都有成本。连接状态、序列号、ACK确认、重传、拥塞控制、滑动窗口,全都要维护。TCP像个项目经理,每个需求都建看板、排期、验收、复盘。流程完整,但你问一句中午吃啥也走这套流程,就太重了。

UDP把决定权交出去

UDP无连接,发送方不用先建连接,想发就发。头部只有8字节,TCP最少20字节。无连接、延迟更低、没有队头阻塞、应用自己可控。

代价是UDP本身不保证:一定送达、按序到达、不重复、对方收到、拥塞时自动降速。这些都可以在UDP之上由应用自己实现,QUIC就是典型例子,HTTP/3就跑在QUIC上。

最本质的差异:字节流和数据报

TCP是字节流协议。应用写入的数据在对端读出来时,不保证保持原来的消息边界。发送两次write,对端可能一次读到helloworld,也可能分多次读到he、llow、orld。

所以用TCP的应用协议要自己设计分包方式:固定长度、分隔符、长度字段,选一种。

UDP是数据报协议。一次send对应一个数据报,消息边界天然存在。所谓粘包不是TCP的错,TCP本来就是字节流,是应用层协议没把边界设计好。

可靠性不是免费的

TCP的可靠来自一组机制配合:序列号给字节流编号,接收方知道哪些到了哪些没到;ACK确认告诉发送方收到了哪一段;超时未确认就重传;接收端重排乱序包实现有序交付;窗口调整发送速率做流量控制;拥塞控制根据网络状况自动降速。

代价是延迟、状态、复杂度和带宽开销。UDP不保证可靠,但应用可以在它上面实现可靠策略,比如QUIC。准确说,UDP把可靠策略交给更懂业务的应用层去定。

场景怎么选

Web页面、HTTPS、文件传输走TCP,因为需要可靠有序。DNS查询、视频直播、在线游戏、语音通话走UDP,因为更看重实时性或低开销。HTTP/3基于UDP上的QUIC,想兼顾可靠和性能。

实时场景偏爱UDP有具体原因。语音通话丢一小段可以插值补偿,如果停下来等重传,后续音频会全部卡住。在线游戏某一帧的位置包丢了,下一帧马上就到,重传旧位置没有意义。

文件传输偏爱TCP。少一个字节都可能损坏文件,完整、有序、不重复、能重传正是TCP擅长的。用UDP自己实现可靠文件传输当然可以,但大多数普通业务没必要重造半个TCP。

这里有个坑:选型不是看协议本身谁更高级,而是看这段数据过期之后还有没有价值。

五个常见误区

误区一:TCP一定比UDP慢。实际性能取决于网络质量和应用设计,设计糟糕的UDP应用可能比TCP还慢。

误区二:UDP不会丢包。UDP本身不保证不丢,局域网丢包概率低,但低概率不等于协议保证。

误区三:TCP是消息协议。TCP是字节流,不保留消息边界,粘包和半包是应用层没设计好边界。

误区四:UDP不能做可靠传输。应用可以在UDP上实现可靠传输,比如QUIC,真正的问题是你要不要自己做。

误区五:可靠性越强越好。实时音视频里,过期数据重传不如直接丢弃。可靠性是目标之一,不是唯一目标。

一个可验证的判断方法

拿不准的时候,先别争论协议,做一次抓包看行为。用tcpdump抓一段业务流量:

判定标准很直接。如果抓包里出现大量重传、重复ACK、窗口缩小,说明这条链路上TCP已经在为可靠性付出延迟代价,实时业务可以考虑换UDP或QUIC。如果UDP流量抓下来发现丢包率在可接受范围内,且应用能容忍局部丢失,那就没必要在UDP上再堆一套重传。

补充一个容易忽略的工程事实:TCP的拥塞控制算法在不同内核版本上默认值不一样,Linux从4.9起默认改为BBR的发行版并不多,多数主流发行版仍以CUBIC为默认。同一份业务代码换内核或换云厂商,吞吐表现可能变化,压测时要把这个变量固定住。

协议选择没有高低之分,只有合不合适。TCP把可靠性内置在传输层,UDP把选择权交给应用层。

Feng
这位作者很神秘,还没有填写简介。