欢迎光临
我们一直在努力

Python Socket 套接字完全讲解

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 核心区别(高频)

对比维度TCPUDP
连接方式 面向连接(三次握手) 无连接
可靠性 可靠(序列号、确认应答、超时重传) 不可靠(发出去不保证收到)
数据形式 流式数据(无边界) 数据报(有边界,一发一收)
速度 较慢(有握手、重传开销) 较快(无额外开销)
适用场景 登录、聊天、文件传输、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的区别

赞(0)
未经允许不得转载:171主机测评 » Python Socket 套接字完全讲解
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址