问题:TCP 和 UDP 协议,Socket 编程中基础的区别是什么(简单说明)?

TCP 和 UDP 在 Socket 编程中的基础区别

【课堂段子】
潘老师讲课,活脱脱一个TCP协议——面向连接,第一节课必先“三次握手”:
“同学们都在吗?”(SYN)
“在!”(SYN-ACK)
“好,那我开始讲了!”(ACK)
全员到位才开腔,这叫仪式感。

讲课过程更是可靠传输:每讲一个知识点,必须全班点头确认(ACK),谁眼神飘忽,立马重传——代码敲五遍,笔记抄三回,直到潘老师确认“接收窗口已满”才肯翻页。字节流传输嘛,一个字节都不能丢,标点符号错了都要回滚重发。

下课更讲究,四次挥手:
“我要下课了。”(FIN)
“等等,我把这页笔记抄完。”(ACK)
“我抄完了,您下吧。”(FIN)
“好,同学们再见,明天见。”(ACK)
挥完手还要等两分钟,确保没人提问才真正断开,礼貌得让隔壁班羡慕。

反观隔壁大学老师,那是UDP风格——广播式公开课,进门就开讲,叭叭叭一顿输出,语速快得像2倍速,速度好,不要回复,不管你听不听得见、会不会,下课铃一响,拎包走人,连“再见”都省了,主打一个“快意恩仇”。

潘老师走出教室,元气满满叹一句:“还是TCP踏实啊,每个包都活着回来。”
而UDP老师早已在食堂窗口前,遥遥领先。
——这一天,同学们在确认与重传中,终于学会了什么叫 “可靠” 。😄

一句话回答

TCP 是面向连接、可靠、流式传输;UDP 是无连接、不可靠、数据报传输。
Socket 编程中:TCP 用 send/recv 需先 connect/accept;UDP 直接用 sendto/recvfrom,无需建立连接。

核心区别(面试必背)

对比维度 TCP UDP
连接状态 面向连接(三次握手) 无连接(直接发,不握手)
可靠性 可靠(确认重传、有序到达) 不可靠(可能丢包、乱序)
传输方式 流式(Stream) :无消息边界,需应用层处理粘包 数据报(Datagram) :有消息边界,每个包完整独立
速度/开销 慢(握手、校验、重传开销大) 快(轻量,无额外校验)
Socket 方法 connect()、accept()、send()、recv() sendto()、recvfrom()(无需连接)
适用场景 HTTP、文件传输、邮件、数据库连接 视频直播、DNS 查询、游戏位置更新、语音通话

核心代码对比

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# ---------- TCP(面向连接)----------
# 服务端:监听 + 接受
server.bind(("0.0.0.0", 8888))
server.listen()
conn, addr = server.accept() # 建立连接
conn.send(b"Hello") # 用连接套接字发送

# 客户端:先连接
client.connect(("127.0.0.1", 8888))
client.send(b"Hi")

# ---------- UDP(无连接)----------
# 服务端:只绑定,不监听/接受
udp_server.bind(("0.0.0.0", 8888))
data, addr = udp_server.recvfrom(1024) # 直接收,返回数据和地址
udp_server.sendto(b"Hello", addr) # 直接发给指定地址

# 客户端:不连接,直接发
udp_client.sendto(b"Hi", ("127.0.0.1", 8888))
data, addr = udp_client.recvfrom(1024)

面试高频陷阱

Q1:TCP 为什么会有“粘包”问题?

TCP 是流式传输,不保留消息边界。多次 send 可能被一次 recv 收走(粘包),需应用层自定义协议(如固定长度、分隔符、长度头)。

Q2:UDP 会粘包吗?

不会。 UDP 是数据报,每个 sendto 对应一个完整的 recvfrom,有明确边界。但可能丢包或乱序。

Q3:UDP 需要 listen/accept 吗?

不需要。 UDP 无连接,没有“监听等待连接”的概念,只需 bind 绑定端口后直接 recvfrom。

背诵模板

“TCP 面向连接可靠,用 send/recv,适合文件/HTTP;UDP 无连接不可靠但快,用 sendto/recvfrom,适合直播/DNS。TCP 注意粘包(自定义协议),UDP 注意丢包(容忍丢失)。”