端到端的“两极对话”:TCP和UDP,你天天用却未必懂

张开发
2026/4/17 2:08:26 15 分钟阅读

分享文章

端到端的“两极对话”:TCP和UDP,你天天用却未必懂
面试官“TCP和UDP有什么区别”我“TCP是面向连接的可靠传输UDP是无连接的不可靠传输……”面试官“那你在项目里什么时候用TCP什么时候用UDP”我“呃……好像都没用过”写在前面这是很多人真实的内心戏。包括我自己日常写Java业务代码一个HTTP走天下好像根本不需要纠结什么TCP还是UDP。直到有一天我在“知识汇”教育平台里搞高并发秒杀用RedisLua做库存扣减的时候忽然意识到SpringCloud的Feign调用是HTTP→TCPWebSocket是TCP长连接DNS解析用的是UDP——原来TCP和UDP一直藏在我写的每一行“远程调用”背后只是我没看见。今天我们就从后端开发者的视角出发把传输层的这两个“灵魂人物”彻底捋清楚它们是谁区别在哪你在开发中到底和它们打过多少次照面以及下次自己设计通信方案时到底该怎么选一、开篇一张图TCP vs UDP 核心对比核心差异速览二、TCP那个永远要确认的“老实人”2.1 TCP 的“三大规矩”TCP的设计哲学只有一个字稳。它通过三大机制保证数据万无一失三次握手 → 四次挥手通信前先确认双方都在线结束后体面告别绝不“不告而别”。确认重传发出去的数据必须等对方说“收到了”没听到就重发。流量控制拥塞控制根据网络状况和对方接收能力动态调整发送速度不会“把对方撑死”也不会“把网络堵死”。2.2 为什么是“字节流”而不是“消息”TCP是面向字节流的——应用层交给TCP一个100字节的数据TCP可能拆成两个50字节的包发出去也可能和后面的数据合并。接收方拿到的是没有边界的一串字节需要自己想办法“切回原来的消息”。这就是开发中常说的“TCP粘包问题”。面试官常问TCP粘包怎么解决答固定消息长度、使用分隔符比如换行符、在消息头里加长度字段。2.3 开发中的TCP你每天都在用它你以为你在用HTTP其实你在用TCP。HTTP是应用层协议底层跑的正是TCP。Feign/SpringCloud微服务调用你在Controller里写GetMappingFeign帮你生成动态代理底层通过HttpClient发送HTTP请求HTTP基于TCP传输。WebSocket先在TCP上完成HTTP Upgrade握手升级成WebSocket协议之后保持TCP长连接适合实时推送。数据库连接MySQL默认端口3306Redis默认6379——底层全是TCP长连接。SSH登录服务器基于TCP保证你敲的每一条命令都完整到达。2.4 Java中怎么玩TCPJDK原生提供了Socket和ServerSocket// 服务端 ServerSocket server new ServerSocket(8080); Socket client server.accept(); BufferedReader in new BufferedReader(new InputStreamReader(client.getInputStream())); String msg in.readLine(); System.out.println(收到: msg); // 客户端 Socket socket new Socket(localhost, 8080); PrintWriter out new PrintWriter(socket.getOutputStream(), true); out.println(Hello TCP!);但高并发场景下传统的BIO模式一个连接一个线程撑不住。这时候就要请出Netty——一个异步事件驱动的NIO框架被Dubbo、Elasticsearch等众多知名项目采用轻松支持数万并发连接。三、UDP那个“爱谁谁”的快递员3.1 UDP 的“三大特点”UDP的设计哲学是快就完事了。无连接发之前不打招呼收之后不回确认。不可靠丢包了不重传乱序了不重排。轻量头部只有8字节比TCP的20字节省了不少。3.2 什么场景用UDP对丢包不敏感、但对延迟敏感的场景UDP是王者视频通话/直播画面偶尔花一下没关系但要等重传就卡成PPT了。在线游戏CSGO里你开了一枪宁可丢一发子弹数据也不能等重传——等到了你人可能已经死了。DNS查询发一个几十字节的请求收一个几十字节的响应建TCP连接的开销比查询本身还大。IoT传感器上报每秒上报上千个温度数据丢一两个无所谓实时性更重要。3.3 Java中怎么玩UDP// UDP 服务端 DatagramSocket socket new DatagramSocket(9090); byte[] buf new byte[1024]; DatagramPacket packet new DatagramPacket(buf, buf.length); socket.receive(packet); String msg new String(packet.getData(), 0, packet.getLength()); System.out.println(收到: msg); // UDP 客户端 DatagramSocket socket new DatagramSocket(); byte[] buf Hello UDP!.getBytes(); DatagramPacket packet new DatagramPacket(buf, buf.length, InetAddress.getByName(localhost), 9090); socket.send(packet);和TCP相比UDP的API更简单但你也失去了TCP提供的一切“保姆级服务”。四、那么问题来了我到底该用TCP还是UDP4.1 从零设计通信方案时怎么选做技术选型问自己三个问题Q1数据丢了能不能忍不能忍转账、订单、文件传输→TCP能忍视频帧、传感器数据、游戏坐标→ 考虑UDPQ2顺序乱了行不行不行聊天消息、命令执行→TCP行视频解码、多路径上报→ 考虑UDPQ3延迟敏感还是完整性敏感完整性优先 →TCP延迟优先 →UDP4.2 一个万能话术混合使用面试官问“视频会议系统怎么设计通信协议”标准答案“视频流和音频流用UDP保证低延迟控制信令加入房间、静音、踢人用TCP保证可靠性。”4.3 进阶在UDP上“模拟”TCP如果既要UDP的低延迟又要TCP的可靠性怎么办自己实现。QUIC协议HTTP/3底层Google在UDP上实现了类似TCP的可靠性机制。WebRTC视频通话底层用UDP但自己做了丢包重传、拥塞控制。游戏同步协议比如守望先锋的“回滚式同步”就是在UDP上做的。4.4 开发中一个容易犯的错在公司写一个实时数据推送服务技术选型时选了WebSocket基于TCP。上线后发现延迟高排查半天原来用户量一大TCP的拥塞控制自动降速了。后来换成UDP应用层丢包容忍流畅度明显提升。所以选TCP还是UDP没有绝对的好坏只有适配的场景。五、总结把八股变成肌肉记忆这次在知识汇教育平台里做高并发秒杀缓存数据一致性用RedisTCP用户行为日志上报用UDP——丢几条日志不影响业务但能减轻服务器压力。下次面试官再问“TCP和UDP的区别”别只背八股扔出你的项目经验告诉他“我在知识汇的秒杀系统里核心数据走TCP保证可靠性日志埋点走UDP提升吞吐量。”这才是面试官想听到的答案。

更多文章