Python——网络编程,如何避免死锁?
问题描述:什么是死锁?
死锁发生在当一个服务器和客户端同时试图往一个连接上写东西或同时从一个连接上读的时候。在这种情况下,没有进程可以得到任何数据(如果它们都正在读),因此,如果它们正在写,向外的buffer会被充满,结果他们就好象被骗了,什么都做不了。
示例服务器代码:
import socket,traceback host=""
port=51423 sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)
sock.bind((host,port))
sock.listen(1) while True:
try:
clientsock,clientaddr= sock.accept()
except KeyboardInterrupt:
raise
except:
traceback.print_exc()
continue try:
print("Got connection from ",clientsock.getpeername)
while True:
data = clientsock.recv(4096)
if not len(data):
break
clientsock.sendall(data)
except (KeyboardInterrupt,SystemExit):
raise
except:
traceback.print_exc() try:
clientsock.close()
except KeyboardInterrupt:
raise
except:
traceback.print_exc()
示例客户端代码:
import socket
import sys port=51423
host="localhost" data=b"x"*10485760
sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sock.connect((host,port)) byteswritten=0
while byteswritten<len(data):
startpos = byteswritten
endpos = min(byteswritten+1024,len(data))
byteswritten+=sock.send(data[startpos:endpos])
sys.stdout.write("wrote %d bytes\r"% byteswritten)
sys.stdout.flush() sock.shutdown(1) print("All data sent.")
while True:
buf = sock.recv(1024).decode()
if not len(buf):
break
sys.stdout.write(buf)
在运行上述服务器代码的情况下运行客户端代码,得到如下结果:
服务器:
(ev1)[root@Simonxu bin]# python testserver.py
Got connection from <built-in method getpeername of socket object at 0x7f5e18d2b460>
客户端:
(ev1)[root@Simonxu bin]# python test.py
wrote bytes
可以看出,上述服务器和客户端卡在的wrote 164864 bytes。
-------------------------------------------------------------------分析--------------------------------------------------------------------------------------------
已知客户端程序试图发送一个10MB的数据,每次传输1KB,同时显示发送数据动态,并在所有数据发送完成后,从服务器每次1KB读取并写数据。
而服务器在建立套接口连接后,从客户端每次读取4KB数据,在接收到数据后,直接把数据发回客户端。
而矛盾的是,由于客户端在发送一个10MB大小的数据,这要发送较长时间,在发送的过程中没有办法读取数据,因此服务器返回的数据就堆积在客户端的接收缓冲区。
当接收缓冲区满了之后,服务器的sendall()函数发生错误,循环死锁,服务器不再接收客户端发来的数据。客户端也无法继续发送数据。就形成了上面的情况。
------------------------------------------------------------------如何避免死锁?----------------------------------------------------------------------------------
1、可以在客户端每次执行完send()后,进行一次recv()以接收服务器发来的数据,避免buffer充满。
2、可以让客户端发送的数据较少,这样在buffer充满之前就可以从缓冲区读取服务器发回的数据。
3、采用多线程或其他一些方法,使客户端可以同时发送和接收。
-----------------------------------------------------------------知识补充------------------------------------------------------------------------------------------
缓冲区:
1. tcp 收发缓冲区默认值
[root@ www.linuxidc.com]# cat /proc/sys/net/ipv4/tcp_rmem
4096 87380 4161536
87380 :tcp接收缓冲区的默认值
[root@ www.linuxidc.com]# cat /proc/sys/net/ipv4/tcp_wmem
4096 16384 4161536
16384 : tcp 发送缓冲区的默认值
2. tcp 或udp收发缓冲区最大值
[root@ www.linuxidc.com]# cat /proc/sys/net/core/rmem_max
131071
131071:tcp 或 udp 接收缓冲区最大可设置值的一半。
也就是说调用 setsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcv_size, &optlen); 时rcv_size 如果超过 131071,那么
getsockopt(s, SOL_SOCKET, SO_RCVBUF, &rcv_size, &optlen); 去到的值就等于 131071 * 2 = 262142
[root@ www.linuxidc.com]# cat /proc/sys/net/core/wmem_max
131071
131071:tcp 或 udp 发送缓冲区最大可设置值得一半。
跟上面同一个道理
3. udp收发缓冲区默认值
[root@ www.linuxidc.com]# cat /proc/sys/net/core/rmem_default
111616:udp接收缓冲区的默认值
[root@ www.linuxidc.com]# cat /proc/sys/net/core/wmem_default
111616
111616:udp发送缓冲区的默认值
4. tcp 或udp收发缓冲区最小值
tcp 或udp接收缓冲区的最小值为 256 bytes,由内核的宏决定;
tcp 或udp发送缓冲区的最小值为 2048 bytes,由内核的宏决定
Python——网络编程,如何避免死锁?的更多相关文章
- 8.Python网络编程_多线程死锁
死锁:指两个或两个以上的线程在执行过程中,由于竞争资源或者由于彼此通信而造成的一种阻塞的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死 ...
- python网络编程应用(一)
在之前的一篇博客<python网络编程基础>中介绍了socket.socket()函数及其应用,其实socket模块中还有很多属性可供网络应用程序使用.这里将详细讲解一下socket模块 ...
- Python 网络编程(二)
Python 网络编程 上一篇博客介绍了socket的基本概念以及实现了简单的TCP和UDP的客户端.服务器程序,本篇博客主要对socket编程进行更深入的讲解 一.简化版ssh实现 这是一个极其简单 ...
- Python 网络编程(一)
Python 网络编程 socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,应用程序通常通过"套接字"向网络发出请求或者应答网络请求. ...
- Python学习(22)python网络编程
Python 网络编程 Python 提供了两个级别访问的网络服务.: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口的 ...
- Day07 - Python 网络编程 Socket
1. Python 网络编程 Python 提供了两个级别访问网络服务: 低级别的网络服务支持基本的 Socket,它提供了标准的 BSD Sockets API,可以访问底层操作系统Socket接口 ...
- python网络编程-01
python网络编程 1.socket模块介绍 ①在网络编程中的一个基本组件就是套接字(socket),socket是两个程序之间的“信息通道”. ②套接字包括两个部分:服务器套接字.客户机套接字 ③ ...
- 《Python网络编程》学习笔记--使用谷歌地理编码API获取一个JSON文档
Foundations of Python Network Programing,Third Edition <python网络编程>,本书中的代码可在Github上搜索fopnp下载 本 ...
- Python网络编程基础pdf
Python网络编程基础(高清版)PDF 百度网盘 链接:https://pan.baidu.com/s/1VGwGtMSZbE0bSZe-MBl6qA 提取码:mert 复制这段内容后打开百度网盘手 ...
- python 网络编程(Socket)
# from wsgiref.simple_server import make_server## def RunServer(environ,start_response):# start_resp ...
随机推荐
- pandas求五日线并画图
import pandas as pd import numpy as np import matplotlib.pyplot as plt stock_data = pd.read_csv('000 ...
- mybatis-config.xml的解释(zz)
<!-- xml标准格式 --><?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ...
- 构建maven动态web 工程
项目构建 总体参考: http://www.java2blog.com/2015/09/how-to-create-dynamic-web-project-using.html https://sta ...
- [BZOJ4556][Tjoi2016&Heoi2016]字符串 主席树+二分+倍增+后缀自动机
4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 1215 Solved: 484[S ...
- 7/26 CSU-ACM2018暑期训练3-递归&递推-选讲
题目链接 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法. Input 第一行是测试数据的数目t(0 <= ...
- 《Machine Learning》(第一章)序章
关键词:机器学习,基本术语,假设空间,归纳偏好,机器学习用途 一.机器学习概述 机器学习是一门从数据中,经过计算得到模型(Model)的一种过程,得到的模型不仅能反应出训练数据集中所蕴含的规律,并且能 ...
- 【bzoj2763】[JLOI2011]飞行路线 (分层图最短路)(优先队列dij)
[bzoj2763][JLOI2011]飞行路线 2014年3月25日1,7260 Description Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在n个城 ...
- UVA 839 Not so Mobile (递归建立二叉树)
题目连接:http://acm.hust.edu.cn/vjudge/problem/19486 给你一个杠杆两端的物体的质量和力臂,如果质量为零,则下面是一个杠杆,判断是否所有杠杆平衡. 分析:递归 ...
- ASP.NET Core 2.2 基础知识(一) 依赖注入
依赖: 类A用到了类B,我们就说类A依赖类B.如果一个类没有任何地方使用到,那这个类基本上可以删掉了. public class Test { private MyDependency md = ne ...
- [BZOJ 1789] Necklace
Link: BZOJ 1789 传送门 Solution: 感觉$n\le 50$可以随便乱搞啊…… 这里我是先找到3条链的失配位置,再找到这之后其中2条链最远的失配位置,统计即可 Code: #in ...