尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

网络通信中的死锁

网络通信中的死锁
📅 发布时间:2026/6/17 18:05:08

客户端代码

点击查看代码
import socket
from pathlib import PathSERVER_ADDRESS = Path("/tmp/uds_socket")
CHUNK_SIZE = 1024def main():# Create Unix Domain Socket in client sidewith socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s:s.connect(str(SERVER_ADDRESS))s.sendall(b"Hello from client")response = b""while data := s.recv(CHUNK_SIZE):response += dataprint(response.decode())if __name__ == "__main__":main()

服务端代码

点击查看代码
import socket
from pathlib import PathSERVER_ADDRESS = Path("/tmp/uds_socket")
CHUNK_SIZE = 1024def main():# If the socket file already exists, remove itif SERVER_ADDRESS.exists():SERVER_ADDRESS.unlink()# Create Unix Domain Socket in server sidewith socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s:s.bind(str(SERVER_ADDRESS))s.listen(16)print(f"[*] Listening at {str(SERVER_ADDRESS)}...")while True:try:conn, _ = s.accept()except KeyboardInterrupt:print("\n[*] Shutting down server...")breakwith conn:request = b""while data := conn.recv(CHUNK_SIZE):request += dataprint(f"[From client]: {request.decode()}")conn.sendall(b"Hello from server")conn.shutdown(socket.SHUT_WR)if __name__ == "__main__":main()

启动服务端,然后运行客户端就会出现死锁:客户端和服务端都阻塞在recv方法上,具体过程和解决办法分析如下

  1. 过程

启动服务端,服务端首先阻塞在accept上
启动客户端,客户端成功连接服务端,服务端从accept返回,然后阻塞在recv方法上
客户端使用sendall发送数据之后也阻塞在recv方法上,至此死锁就发生了!

  1. 解决办法

这是经典的死锁发生的必要条件之一:循环等待。
客户端在发送完数据之后应该将自己的状态设置为半关闭状态,然后客户端也会将自己的半关闭状态通知给客户端。
服务端的接收缓冲区为空,因此recv方法会一直阻塞,除非发生以下两种情况之一:

  • 客户端发送通知自己是半关闭状态
  • 客户端发送通知自己是全关闭状态

服务端收到客户端的半关闭或者全关闭通知之后,会从recv方法中返回,获得一个空字节串,然后结束while循环。
服务端使用sendall方法发送所有数据,然后进入半关闭状态,然后进入全关闭状态。
客户端recv方法收到数据并且知道了服务端处于半关闭或者全关闭状态,就会从recv方法中返回,获得一个空字节串,然后结束while循环。
解决办法:在客户端发送万数据之后,添加一段代码s.shutdown(socket.SHUT_WR)。
在服务端代码中,shutdown方法不是必要的,因为服务端代码在sendall之后,即使没有使用shutdown进入半关闭状态,也会关闭自己的socket,进入全连接状态
但是,如果客户端/服务端确认自己不会再发送数据了,关闭自己的写端进入半关闭状态可以让代码更健壮。

修改后的客户端代码

点击查看代码
import socket
from pathlib import PathSERVER_ADDRESS = Path("/tmp/uds_socket")
CHUNK_SIZE = 1024def main():# Create Unix Domain Socket in client sidewith socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as s:s.connect(str(SERVER_ADDRESS))s.sendall(b"Hello from client")# TODO client.shutdown is very important, otherwise server won't get EOF and keep waiting for data# TODO then client and server will be deadlocked!!!s.shutdown(socket.SHUT_WR)  response = b""while data := s.recv(CHUNK_SIZE):response += dataprint(response.decode())if __name__ == "__main__":main()

运行结果

image

相关新闻

  • CSP-S模拟19
  • union类型
  • 学习笔记

最新新闻

  • 2026 安徽哪所学校护理升学强?5大高升学率中职招生名单 - 小途xt
  • NXP DPAA硬件加速实战:报文头操作与CAAM加密引擎配置详解
  • 2026年论文写作AI工具怎么用?豆包等工具详细使用教程 - 掌桥科研-AI论文写作
  • 2026滁州家长注意!离南京这么近,孩子学建筑去这所公办中职,比在南京打工强 - 我叫小周
  • 50行Python实现人脸检测:OpenCV+Haar级联原理与实战
  • 2026重庆高端珠宝首饰回收排行 权威鉴定实测靠谱商家榜单 - 名奢变现站

日新闻

  • 2026年不锈钢卷板厂家推荐排行榜:冷轧热轧/304/201不锈钢卷板,高颜值耐腐蚀源头厂家实力精选 - 企业推荐官【官方】
  • FLUX.1-dev FP8模型实战指南:24GB以下显卡高效部署方案
  • 2026佛山长途搬家价目表:跨省跨市搬家费用完整计算指南 - 从来都是英雄出少年

周新闻

  • 3步解锁iOS设备:applera1n激活锁绕过完全指南
  • 39 2026 人工智能证书终极盘点,普通人选 AI 证书可以从这些方向入手
  • Redis 暴露公网有多危险?从端口检查到补救步骤

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号