02Socket通信的基本流程是什么(客户端和服务端)?
文章目录
问题: Socket 通信的基本流程是什么(客户端和服务端)?
👇 点击展开/折叠 面试背诵模板(建议先背这个)
服务端与客户端核心调用对照表
| 阶段 | 服务端调用 | 客户端调用 | 说明 |
|---|---|---|---|
| 创建套接字 | socket() |
socket() |
指定地址族(AF_INET)和协议(SOCK_STREAM) |
| 绑定地址 | bind() |
(可选) | 服务端需固定端口,客户端由系统分配临时端口 |
| 监听/连接 | listen() |
connect() |
服务端进入被动队列,客户端发起三次握手 |
| 接受连接 | accept() |
(阻塞等待) | 返回新的客户端套接字 fd |
| 数据收发 | recv() / send() |
recv() / send() |
应用层协议解析,注意粘包问题 |
| 关闭连接 | close() |
close() |
触发四次挥手释放资源 |
TCP 三次握手与 accept/connect 的对应关系
- 客户端调用
connect()后,内核发送 SYN 包,进入 SYN_SENT 状态。 - 服务端在
listen()后,内核收到 SYN 回复 SYN+ACK,进入 SYN_RCVD 状态。 - 客户端收到 SYN+ACK 回复 ACK,进入 ESTABLISHED,
connect()返回。 - 服务端收到 ACK 进入 ESTABLISHED,但
accept()仅在完成队列中有连接时返回(三次握手完成后)。因此accept()的返回标志着连接已可用,而非正在握手。
Python 代码模拟(TCP 回显服务)
1 | # server.py(服务端) |
三次握手与四次挥手的核心时序(补充)
| 阶段 | 触发动作 | 网络包 | 状态变化 |
|---|---|---|---|
| 三次握手 | connect() 客户端发起 |
SYN →, ← SYN+ACK, ACK → | CLOSED → ESTABLISHED |
| 数据传输 | send() / recv() |
PSH/ACK 数据包 | ESTABLISHED |
| 四次挥手 | 主动调用 close() |
FIN →, ← ACK, ← FIN, ACK → | FIN_WAIT → CLOSED |
常见阻塞点与 I/O 模型选择
accept()、recv()、connect()默认均为阻塞调用,若需非阻塞,需设置setblocking(False)或使用select/poll/epoll多路复用。- 阻塞
recv()在连接断开时返回空字节串(b’’),需据此检测对端关闭。 - 大并发场景下,单线程阻塞模型无法应对,建议使用多线程(每连接一线程)或异步 IO(如 asyncio)和事件驱动框架(如 Twisted、Tornado)。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 LGQ的博客!