Python Socket 套接字完全讲解(含网络模型图解)
一、Socket 核心概念
Socket(套接字)是 Python 实现网络通信的核心接口,本质是 两台主机之间通信的“端点”,是操作系统提供的传输层编程接口(API),负责在网络中建立连接、发送数据、接收数据。
类比理解:
-
网络 = 电话线
-
Socket = 话筒/听筒(通信端点)
-
send() = 说话(发送数据)
-
recv() = 听话(接收数据)
核心特点:
-
跨平台:Windows、Linux、Mac 通用
-
支持 TCP、UDP 两种主流传输协议
-
是 HTTP、FTP、SSH 等高层协议的底层基础
二、Socket 与网络模型的关系(含图解)
Socket 不属于 OSI 七层模型/ TCP/IP 五层模型中的某一层,而是 传输层与应用层之间的“桥梁”,封装了底层网络协议(TCP/UDP、IP)的细节,让应用层无需关注底层通信逻辑。
2.1 TCP/IP 五层网络模型(含 Socket 位置)
#mermaid-svg-kP5VAHWywWvUTaGN{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-kP5VAHWywWvUTaGN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-kP5VAHWywWvUTaGN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-kP5VAHWywWvUTaGN .error-icon{fill:#552222;}#mermaid-svg-kP5VAHWywWvUTaGN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-kP5VAHWywWvUTaGN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-kP5VAHWywWvUTaGN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-kP5VAHWywWvUTaGN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-kP5VAHWywWvUTaGN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-kP5VAHWywWvUTaGN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-kP5VAHWywWvUTaGN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-kP5VAHWywWvUTaGN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-kP5VAHWywWvUTaGN .marker.cross{stroke:#333333;}#mermaid-svg-kP5VAHWywWvUTaGN svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-kP5VAHWywWvUTaGN p{margin:0;}#mermaid-svg-kP5VAHWywWvUTaGN .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-kP5VAHWywWvUTaGN .cluster-label text{fill:#333;}#mermaid-svg-kP5VAHWywWvUTaGN .cluster-label span{color:#333;}#mermaid-svg-kP5VAHWywWvUTaGN .cluster-label span p{background-color:transparent;}#mermaid-svg-kP5VAHWywWvUTaGN .label text,#mermaid-svg-kP5VAHWywWvUTaGN span{fill:#333;color:#333;}#mermaid-svg-kP5VAHWywWvUTaGN .node rect,#mermaid-svg-kP5VAHWywWvUTaGN .node circle,#mermaid-svg-kP5VAHWywWvUTaGN .node ellipse,#mermaid-svg-kP5VAHWywWvUTaGN .node polygon,#mermaid-svg-kP5VAHWywWvUTaGN .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-kP5VAHWywWvUTaGN .rough-node .label text,#mermaid-svg-kP5VAHWywWvUTaGN .node .label text,#mermaid-svg-kP5VAHWywWvUTaGN .image-shape .label,#mermaid-svg-kP5VAHWywWvUTaGN .icon-shape .label{text-anchor:middle;}#mermaid-svg-kP5VAHWywWvUTaGN .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-kP5VAHWywWvUTaGN .rough-node .label,#mermaid-svg-kP5VAHWywWvUTaGN .node .label,#mermaid-svg-kP5VAHWywWvUTaGN .image-shape .label,#mermaid-svg-kP5VAHWywWvUTaGN .icon-shape .label{text-align:center;}#mermaid-svg-kP5VAHWywWvUTaGN .node.clickable{cursor:pointer;}#mermaid-svg-kP5VAHWywWvUTaGN .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-kP5VAHWywWvUTaGN .arrowheadPath{fill:#333333;}#mermaid-svg-kP5VAHWywWvUTaGN .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-kP5VAHWywWvUTaGN .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-kP5VAHWywWvUTaGN .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kP5VAHWywWvUTaGN .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-kP5VAHWywWvUTaGN .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kP5VAHWywWvUTaGN .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-kP5VAHWywWvUTaGN .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-kP5VAHWywWvUTaGN .cluster text{fill:#333;}#mermaid-svg-kP5VAHWywWvUTaGN .cluster span{color:#333;}#mermaid-svg-kP5VAHWywWvUTaGN div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-kP5VAHWywWvUTaGN .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-kP5VAHWywWvUTaGN rect.text{fill:none;stroke-width:0;}#mermaid-svg-kP5VAHWywWvUTaGN .icon-shape,#mermaid-svg-kP5VAHWywWvUTaGN .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-kP5VAHWywWvUTaGN .icon-shape p,#mermaid-svg-kP5VAHWywWvUTaGN .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-kP5VAHWywWvUTaGN .icon-shape .label rect,#mermaid-svg-kP5VAHWywWvUTaGN .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-kP5VAHWywWvUTaGN .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-kP5VAHWywWvUTaGN .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-kP5VAHWywWvUTaGN :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
HTTP/FTP/自定义协议
封装/解封装
TCP/UDP
IP 协议
MAC 地址
应用层
Socket 接口
传输层
网络层
数据链路层
物理层
说明:
-
Socket 位于 应用层之下、传输层之上,是应用层调用传输层服务的“入口”。
-
应用层代码(如 Python Socket 程序)通过 Socket 接口,调用传输层的 TCP 或 UDP 协议,完成数据传输。
-
底层的网络层(IP)、数据链路层、物理层,由操作系统和硬件负责,Socket 已封装这些细节,开发者无需关心。
2.2 Socket 与 TCP/UDP 协议的对应关系
Socket 支持两种核心传输模式,分别对应 TCP 和 UDP 协议,适配不同的通信场景:

三、Python Socket 核心用法(分 TCP/UDP)
Python 内置 socket 模块,无需额外安装,直接导入即可使用。核心分为 TCP 和 UDP 两种模式,其中 TCP 是面试和开发中最常用的场景。
3.1 TCP 模式(面向连接,可靠传输)
3.1.1 TCP 通信流程
TCP 通信需先建立连接(三次握手),再收发数据,最后断开连接(四次挥手),流程固定:

TCP 服务端(server.py)
import socket
# 1. 创建 TCP 套接字(AF_INET:IPv4,SOCK_STREAM:TCP)
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 绑定 IP 和端口(IP 为空表示监听所有网卡,端口 8888)
server.bind(('0.0.0.0', 8888))
# 3. 监听连接(backlog:半连接+全连接队列长度,一般设 5~10)
server.listen(5)
print("TCP 服务端已启动,等待客户端连接…")
# 4. 阻塞等待客户端连接(返回:新连接对象 conn + 客户端地址 addr)
conn, addr = server.accept()
print(f"客户端 {addr} 已连接")
# 5. 收发数据(recv(1024):一次最多接收 1024 字节,返回 bytes 类型)
while True:
data = conn.recv(1024)
if not data: # 客户端关闭连接,data 为空
break
print(f"收到客户端 {addr} 消息:{data.decode('utf-8')}")
# 回复客户端
conn.send(f"服务端已收到:{data.decode('utf-8')}".encode('utf-8'))
# 6. 关闭连接(先关客户端连接,再关服务端监听)
conn.close()
server.close()
TCP 客户端(client.py)
import socket
# 1. 创建 TCP 套接字
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2. 连接服务端(IP 为服务端 IP,端口与服务端一致)
client.connect(('127.0.0.1', 8888))
# 3. 收发数据
while True:
msg = input("请输入要发送的消息(输入 'exit' 退出):")
if msg == 'exit':
break
# 发送数据:字符串需 encode 转为 bytes
client.send(msg.encode('utf-8'))
# 接收服务端回复
data = client.recv(1024)
print(f"服务端回复:{data.decode('utf-8')}")
# 4. 关闭连接
client.close()
3.2 UDP 模式(无连接,快速传输)
3.2.1 UDP 通信流程
UDP 无需建立连接,直接发送数据,流程更简单,不保证数据送达和顺序:

3.2.2 可直接运行代码(UDP 服务端 + 客户端)
UDP 服务端(udp_server.py)
import socket
# 1. 创建 UDP 套接字(SOCK_DGRAM:UDP)
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 2. 绑定 IP 和端口
server.bind(('0.0.0.0', 8888))
print("UDP 服务端已启动,等待客户端消息…")
# 3. 收发数据(recvfrom 同时获取数据和客户端地址)
while True:
data, addr = server.recvfrom(1024)
print(f"收到客户端 {addr} 消息:{data.decode('utf-8')}")
# 回复客户端(需指定客户端地址)
server.sendto(f"UDP 服务端已收到:{data.decode('utf-8')}".encode('utf-8'), addr)
# 4. 关闭(可选,UDP 无连接,关闭后停止接收)
# server.close()
UDP 客户端(udp_client.py)
import socket
# 1. 创建 UDP 套接字
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 2. 直接发送数据(无需 connect)
while True:
msg = input("请输入要发送的消息(输入 'exit' 退出):")
if msg == 'exit':
break
# 发送数据:指定服务端 IP 和端口
client.sendto(msg.encode('utf-8'), ('127.0.0.1', 8888))
# 接收服务端回复
data, addr = client.recvfrom(1024)
print(f"服务端回复:{data.decode('utf-8')}")
# 3. 关闭
client.close()
四、Socket 核心方法与参数(必背)
| socket() | 创建套接字 | TCP/UDP | 参数:AF_INET(IPv4)、SOCK_STREAM(TCP)、SOCK_DGRAM(UDP) |
| bind() | 绑定 IP + 端口 | TCP/UDP(服务端) | 参数:元组 (IP, 端口),IP 为空表示监听所有网卡 |
| listen() | 监听连接 | TCP(服务端) | 参数 backlog:连接队列长度,默认 5 |
| accept() | 等待客户端连接 | TCP(服务端) | 阻塞方法,返回 (conn, addr),conn 是新连接对象 |
| connect() | 连接服务端 | TCP(客户端) | 参数:(服务端 IP, 端口),连接失败报 ConnectionRefusedError |
| recv(n) | 接收数据 | TCP | n:最大接收字节数,阻塞方法,返回 bytes 类型 |
| send(data) | 发送数据 | TCP | data:bytes 类型,返回实际发送的字节数 |
| recvfrom(n) | 接收数据 | UDP | 返回 (data, addr),同时获取数据和客户端地址 |
| sendto(data, addr) | 发送数据 | UDP | addr:客户端/服务端地址元组 |
| close() | 关闭套接字 | TCP/UDP | TCP 需先关连接,再关监听;UDP 可直接关闭 |
五、面试高频考点(重点)
5.1 TCP 粘包问题(必考)
1. 什么是粘包?
TCP 是流式协议,数据无边界,多次 send 的数据可能被内核合并成一次接收,导致数据“粘在一起”,称为粘包。
2. 粘包原因:
– 发送端:内核缓冲区合并小数据包(Nagle 算法);
– 接收端:缓冲区未及时读取,多个数据包堆积。
3. 解决方案(最常用):
– 消息头 + 消息长度:先发送“消息长度”(固定字节),再发送消息内容,接收端先读长度,再读对应长度的内容。
5.2 TCP 三次握手与四次挥手(必背)
三次握手(建立连接)

作用:确保双方数据都已传输完成,避免数据丢失。
四次挥手(断开连接)

作用:确保双方数据都已传输完成,避免数据丢失。
5.3 阻塞与非阻塞 Socket
1. 默认模式:阻塞模式
– recv()、accept()、connect() 都会阻塞,直到有数据/连接。
2.非阻塞模式设置:
import socket
server = socket.socket()
server.setblocking(False) # 设置为非阻塞
3. 应用场景:高并发场景(如多客户端连接),需配合 select/epoll 多路复用。
5.4 TCP 与 UDP 核心区别(高频)
| 连接方式 | 面向连接(三次握手) | 无连接 |
| 可靠性 | 可靠(序列号、确认应答、超时重传) | 不可靠(发出去不保证收到) |
| 数据形式 | 流式数据(无边界) | 数据报(有边界,一发一收) |
| 速度 | 较慢(有握手、重传开销) | 较快(无额外开销) |
| 适用场景 | 登录、聊天、文件传输、HTTP | 视频、直播、游戏、DNS |
六、常见问题与避坑指南
-
问题1:bind() 报错 “Address already in use”(地址已被占用)
解决方案:关闭占用该端口的程序,或更换端口,或设置端口复用:
server\\.setsockopt\\(socket\\.SOL\\_SOCKET, socket\\.SO\\_REUSEADDR, 1\\) -
问题2:recv() 接收不到数据/接收不全
原因:recv(n) 一次最多接收 n 字节,大数据需循环接收;TCP 粘包导致数据拆分。
解决方案:循环接收,结合“消息长度”判断是否接收完整。 -
问题3:编码解码报错 “UnicodeDecodeError”
原因:Socket 传输的是 bytes 类型,字符串需 encode 发送,接收后需 decode,编码格式不一致。
解决方案:统一用 utf-8 编码(encode('utf-8')、decode('utf-8'))。 -
问题4:UDP 发送数据后,接收不到回复
原因:服务端/客户端地址绑定错误,或端口不一致,或防火墙拦截。
解决方案:检查 IP 和端口是否一致,关闭防火墙。
七、总结
1. Socket 是 Python 网络通信的核心接口,封装了底层 TCP/UDP 协议,位于应用层与传输层之间。
2. TCP 面向连接、可靠,适合对数据完整性要求高的场景;UDP 无连接、快速,适合实时性要求高的场景。
3. 核心重点:TCP 通信流程、三次握手/四次挥手、粘包问题、核心方法使用。
4. 面试高频:TCP 与 UDP 区别、粘包解决方案、阻塞/非阻塞 Socket、网络模型中 Socket 的位置。
注意:请注意区分websocket与socket的区别




