ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

TCP 与 UDP:从可靠字节流到无连接数据报,怎么选、怎么测

TCP 与 UDP:从可靠字节流到无连接数据报,怎么选、怎么测 TCP 与 UDP从可靠字节流到无连接数据报怎么选、怎么测ℹ️ 读者定位适合你如果会调用 API、配置端口、写 Socket 服务或者正在学习计算机网络但还分不清 TCP 的可靠性、UDP 的消息边界和 QUIC 的关系。开始前需要知道 IP、端口、客户端和服务器不要求先读完 TCP 状态机或内核源码。读完可以完成解释 TCP 三次握手、四次挥手、序列号、重传、窗口和粘包解释 UDP 的边界与风险并按场景选择 TCP、UDP 或基于 UDP 的协议。暂时不适合想看 TCP 拥塞控制算法的数学推导、Linux 内核源码或生产级自定义可靠传输协议设计本文先建立工程判断能力。在工作中我们经常会看到这样的争论文件传输用 TCP音视频用 UDPTCP 可靠但慢UDP 快但不可靠。这个说法有一点道理但拿来直接做架构决策就太粗了。先给结论TCP 把应用数据交付成可靠、有序的字节流UDP 发送一个个独立数据报尽量少替应用做决定。真正选型时先问四个问题数据丢一部分业务还能不能继续数据顺序重要吗旧数据晚到还有价值吗应用需要保留消息边界还是只需要连续字节流重传、拥塞控制和安全能力准备交给谁负责这篇内容分为以下几个部分先建立 TCP 与 UDP 的准确直觉。拆开 TCP 的连接、可靠传输和关闭过程。看懂 UDP 做了什么、没有做什么。用最小命令观察两种协议。通过场景表和 QUIC 关系完成选型。一、先把 TCP 和 UDP 放回传输层1.1 TCP 与 UDP 分别交付什么TCPTransmission Control Protocol传输控制协议向应用提供的是可靠、有序的字节流。UDPUser Datagram Protocol用户数据报协议向应用提供的是独立的数据报。一个数据报可以理解成一条带边界的消息但它可能丢失、重复、乱序协议本身不负责像 TCP 那样补齐这些能力。TCP应用写入 A B C 接收端读到一条连续字节流ABC UDP应用发送[A][B][C]接收端按一个个数据报读取可能收到[A]、[C]也可能丢掉[B]RFC 9293 将 TCP 定义为面向可靠通信的传输协议RFC 768 则将 UDP 定义为最小机制的数据报协议。这两个定位决定了后面所有差异。1.2 四个维度比“快不快”更重要维度TCPUDP连接面向连接需要建立和维护状态无连接不需要 TCP 式连接建立交付可靠、有序、去重后的字节流尽力交付的数据报可能丢失、重复、乱序消息边界不保留应用的消息边界保留数据报边界控制能力TCP 负责确认、重传、窗口和拥塞控制应用或上层协议自行决定是否补这些能力这里一定要注意TCP 的“可靠”不是“业务一定成功”。它只负责把连接中的字节尽力可靠地交给对端 TCP服务器崩溃、应用超时、权限失败TCP 都不能替业务解决。1.3 为什么说 TCP 是字节流假设发送端连续调用三次send(登录);send(用户A);send(密码B);接收端不一定按三次send对应的边界读取。它可能一次读到全部内容也可能先读到“登录用户”再读到“A密码B”。这就是通常所说的 TCP 粘包 / 拆包现象。它不是 TCP 出错而是 TCP 根本没有承诺“保留应用层消息边界”。应用协议需要自己设计长度字段、分隔符、固定长度或其他 framing 规则。消息格式示例|长度|消息体|↓ 先读长度再按长度读取消息体1.4 UDP 的消息边界也不是可靠性保证UDP 一次sendto通常对应接收端的一次数据报读取这让实时音视频、状态同步和简单查询更容易按消息处理。但边界保留不代表消息一定到达。UDP 仍可能遇到网络拥塞导致数据报被丢弃无线网络或路径变化导致乱序应用重复发送导致重复数据数据报过大导致分片、丢包概率增加或被中间设备丢弃。如果业务不能接受这些情况就需要在 UDP 之上增加序列号、确认、重传、过期时间、拥塞控制和加密等机制或者直接选择一个已经提供这些能力的上层协议。TCP 与 UDP 的能力边界二、TCP连接、可靠传输和关闭2.1 TCP 三次握手在确认什么TCP 三次握手不是“为了显得复杂”它要让双方确认彼此的发送与接收能力并同步初始序列号建立连接状态。客户端 服务器|---- SYN ----------------|请求建立连接带初始序列号|--- SYN ACK -----------|确认客户端并发送自己的序列号|---- ACK ----------------|确认服务器的序列号三次握手完成后连接进入ESTABLISHED状态应用数据才会稳定地通过这条 TCP 连接传输。为什么不能只握手两次因为服务器需要知道客户端确实收到了自己的初始序列号和确认第三个ACK让双方对连接建立结果达成一致也能减少历史重复 SYN 造成的错误连接状态。这三个报文只属于 TCP。UDP 没有 TCP 式三次握手如果某个 UDP 应用需要握手那是应用协议自己设计的。2.2 序列号、ACK 和重传怎样配合TCP 给字节编号。发送端把一段数据发出去接收端通过 ACK 告诉发送端“我已经按序收到哪里下一步希望收到哪个序号”。发送端数据序号1000长度500接收端ACK1500表示下一个期望的字节是1500如果发送端在超时时间内没有得到确认或者通过重复 ACK 等现象判断可能丢包就会触发重传或快速恢复机制。实际 TCP 实现还会结合接收窗口、往返时延和拥塞控制调整发送行为。因此TCP 可靠性不是一次性“发出去就完事”而是发送、确认、判断、重传和排序共同完成的。2.3 流量控制和拥塞控制不是一回事这两个概念很容易混在一起机制主要回答的问题关注对象流量控制接收端来不来得及收接收端缓冲区通常体现为接收窗口拥塞控制网络中间路径能不能承受网络链路和路由路径的拥塞程度接收端处理慢时TCP 可以通过窗口告诉发送端先别发太快网络拥塞时TCP 还要降低发送速率避免大量连接把网络拖入拥塞崩溃。TCP 的可靠性和“慢”不能简单画等号。真实吞吐量还受带宽、往返时延、丢包、窗口、拥塞算法、系统参数和应用读写速度影响。2.4 TCP 四次挥手在关闭什么TCP 是全双工连接。客户端和服务器的发送方向可以分别关闭所以典型关闭过程是四个报文客户端 服务器|---- FIN ----------------|客户端没有更多数据发送|--- ACK -----------------|服务器确认收到|--- FIN -----------------|服务器也没有更多数据发送|---- ACK ----------------|客户端确认收到为什么不是三次因为服务器收到客户端的FIN后可能还有剩余数据没有发送完。它可以先回 ACK等数据处理完成后再独立发送自己的 FIN。实际抓包不一定永远是教科书里的四个报文双方同时关闭、连接异常、发送 RST、重传或中间设备行为都会让时序出现变化。但理解“两个方向分别关闭”是关键。主动关闭的一方通常还会进入TIME_WAIT等待一段时间避免旧连接中的延迟报文影响后续使用相同四元组的新连接。服务端看到大量TIME_WAIT不要立即下结论需要结合谁主动关闭、连接频率和系统参数分析。TCP 三次握手、数据传输与四次挥手三、UDP少做一点把控制权交给应用3.1 UDP 首部为什么看起来很短UDP 首部只包含源端口、目的端口、长度和校验和等基本信息协议本身不维护 TCP 那样的连接状态、序列号窗口和确认重传流程。这带来几个直接结果不需要 TCP 三次握手才能发送第一份数据报。没有 TCP 式连接关闭过程。不会因为等待某个丢失数据报而自动补齐有序字节流。应用可以按自己的业务语义处理过期、丢失和重复。省掉机制不等于凭空获得性能。UDP 应用如果自己补齐可靠性最终仍然要承担协议设计、状态维护、重传和拥塞控制的成本。3.2 什么场景可以接受丢包实时系统往往更关心“现在的数据是否新鲜”而不是“历史每一帧是否完整到达”。例如视频通话中一帧画面晚到 500 毫秒补回来也可能没有意义此时丢掉旧帧、继续播放新帧体验可能更好。常见做法包括每个数据报带序列号和时间戳接收端设置抖动缓冲平衡乱序和延迟对关键帧、控制消息使用确认或重传对普通状态更新只保留最新值使用前向纠错或冗余减少少量丢包的影响。这些能力通常来自 RTP、游戏协议、实时通信框架或自定义应用层协议不是 UDP 首部自动提供的。3.3 UDP 也不能无视拥塞和安全UDP 不提供 TCP 式拥塞控制并不意味着应用可以无限速发送。一个不控制速率的 UDP 程序可能压垮自己、局域网或共享链路。生产环境使用 UDP 时至少要考虑报文大小避免不必要的 IP 分片发送速率和拥塞反馈重放、伪造、放大攻击和反射攻击身份认证、完整性保护和必要的加密NAT、状态防火墙和 UDP 可达性。这里一定要注意UDP 简单的是传输层不代表基于 UDP 的生产协议可以简单到不做安全设计。四、用最小实验观察两种协议4.1 先查看本机 TCP 状态Windows PowerShellGet-NetTCPConnection|Sort-Object State, RemotePort|Select-Object-First20Linuxss-tanp你可以重点看LISTEN服务端正在监听ESTABLISHED连接已经建立TIME_WAIT主动关闭的一方等待旧报文消失SYN_SENT/SYN_RECEIVED连接还在建立过程中。☑️ 实际效果图 / GIF 待补充查看 TCP 连接状态请补充真实终端截图展示一个监听端口、一个已建立连接或TIME_WAIT状态注意隐藏公网 IP、用户名和敏感端口。建议文件名截图资源/03-tcp-连接状态.png。4.2 用 netcat 做最小 TCP 实验在接收端执行nc-l9000在发送端执行nc接收端地址9000输入文本后接收端会看到内容。这个实验的重点不是搭建生产服务而是观察 TCP 先建立连接、再传输字节流的过程。不同系统的 netcat 参数可能不同。Windows、Linux 和 macOS 上如果-l行为不一致先执行nc -h按本机版本调整。4.3 用 netcat 做最小 UDP 实验接收端nc-u-l9001发送端nc-u接收端地址9001UDP 实验可能看起来更“直接”没有 TCP 三次握手发送端就可以发数据报。但这不代表对端一定收到也不代表接收端能确认消息没有重复或乱序。☑️ 实际效果图 / GIF 待补充TCP 与 UDP netcat 实验请补充两个终端的真实截图或 GIF展示 TCP 连接建立后传输以及 UDP 直接发送数据报的对比不要把概念图当成实验结果。建议文件名截图资源/04-tcp-udp-netcat.png。4.4 用抓包验证握手和数据报Linux 可以使用sudotcpdump-nianytcp port 9000 or udp port 9001Wireshark 可以使用过滤器tcp.port9000||udp.port9001TCP 抓包重点看 SYN、SYN/ACK、ACK、序列号、确认号和 FINUDP 抓包重点看每个数据报的长度、源/目的端口以及是否出现间隔或丢失。这里的“应该看到什么”是协议层面的观察目标不是固定输出。网卡、系统、工具版本和网络路径都会影响抓包细节。五、场景选择到底该用 TCP 还是 UDP5.1 一张实用选型表场景常见选择为什么需要补充关注文件传输、数据库、网页、普通 APITCP丢失或乱序的数据通常不能直接交给业务连接复用、超时、拥塞和服务端容量DNS 查询UDP 常见单次消息短减少连接状态和等待截断、重试、TCP / DoT / DoH 等替代路径实时音视频UDP / RTP 常见过期数据可能不值得重传编解码、抖动缓冲、拥塞控制、安全在线游戏状态同步UDP 或基于 UDP 的协议可以按新旧状态决定丢弃与补偿可靠控制消息、反作弊、限速设备发现、局域网广播UDP 常见适合一次发送、多个设备接收广播范围、重复、认证和网络隔离HTTP/3QUIC over UDPQUIC 提供连接、流、可靠性和 TLSUDP 可达性、代理、防火墙和回退不要只看应用名字。比如“聊天”可能包含消息发送、在线状态、文件传输和音视频四条链路每条链路的协议选择可以不同。5.2 QUIC 为什么基于 UDPQUIC 使用 UDP 作为底层封装但它不是“裸 UDP”。RFC 9000 描述的 QUIC 自己提供了连接、流、流量控制、拥塞控制、丢包检测和路径迁移并把 TLS 握手集成到连接建立过程中。因此可以这样理解传统 WebHTTP/1.1 或 HTTP/2 → TLS → TCP → IP 现代 WebHTTP/3 → QUIC包含 TLS 与可靠流→ UDP → IPQUIC 之所以基于 UDP是为了让上层传输协议拥有更大的演进空间避免被操作系统内核中固定的 TCP 行为完全限制。但它仍然要面对网络丢包、拥塞和 UDP 被拦截等现实问题。5.3 一个简单的决策顺序如果你在做新协议或新服务可以按这个顺序判断数据是否必须完整、有序到达是的话先考虑 TCP 或可靠的上层协议。数据是否有明确消息边界有的话UDP 或在 TCP 上设计 framing 都可以不要误以为 TCP 自动保留边界。旧数据晚到是否仍有价值没价值时UDP / QUIC 流或实时协议可能更适合但要补齐控制与安全。你是否有能力维护可靠性、拥塞控制和安全没有的话优先使用成熟协议不要从裸 UDP 开始造轮子。六、常见误区与最后记忆点6.1 常见误区TCP 一定比 UDP 慢。TCP 的握手、确认和控制会带来机制成本但实际性能取决于网络、实现、数据量和应用需求。UDP 没有连接所以不需要状态。UDP 没有 TCP 式连接状态但应用完全可以自己维护会话、序列号和认证状态。UDP 丢包就不能用。实时媒体和状态同步可以按业务容忍丢失、过期和乱序但必须明确补偿策略。TCP 粘包是网络故障。TCP 是字节流应用需要自己设计消息 framing。QUIC 就是 UDP 加 TLS。QUIC 还提供流、可靠传输、拥塞控制、连接 ID 和路径迁移等传输能力。三次握手和四次挥手适用于所有协议。它们是 TCP 的连接建立与关闭过程不是 UDP 的固定流程。6.2 最后记住这句话TCP我帮你把字节可靠、有序地送到对端但不保留消息边界。 UDP我帮你发出一个个数据报消息边界在但可靠性要你自己决定。 QUIC我在 UDP 上重新提供现代传输能力并集成 TLS。工程上不要先问“哪个更快”而要先问数据能不能丢、顺序重不重要、边界谁负责、控制机制谁维护。参考资料RFC 9293 - Transmission Control ProtocolRFC 768 - User Datagram ProtocolRFC 8095 - Services Provided by IETF Transport ProtocolsRFC 9000 - QUICRFC 3550 - RTPRFC 8085 - UDP Usage Guidelines
返回列表