python-day38--IO模型
一、 IO模型介绍
对于一个网络通信,IO涉及到两个阶段
1.操作系统等数据来
2.进程或线程等操作系统拷贝数据
记住这两点很重要,因为这些IO模型的区别就是在两个阶段上各有不同的情况。
二、阻塞IO(blocking IO)
例子:
from socket import *
s=socket(AF_INET,SOCK_STREAM)
s.bind(('127.0.0.1',8080))
s.listen(5)
print('starting..')
while True:
conn,addr=s.accept() # accept就是IO
print(addr)
while True:
try:
data=conn.recv(1024) #recv 也是IO
if not data : break
conn.send(data.upper())
except Exception:
break
conn.close()
s.close()
socket 通信服务端
from socket import *
c=socket(AF_INET,SOCK_STREAM)
c.connect(('127.0.0.1',8080)) while True:
cmd=input('ss').strip()
if not cmd:continue
c.send(cmd.encode('utf-8'))
data=c.recv(1024)
print(data.decode('utf-8'))
socket 通信客户端
所以,blocking IO的特点就是在IO执行的两个阶段(等待数据和拷贝数据两个阶段)都被block了。
一个简单的解决方案:
#在服务器端使用多线程(或多进程)。多线程(或多进程)的目的是让每个连接都拥有独立的线程(或进程),这样任何一个连接的阻塞都不会影响其他的连接。
该方案的问题是:
#开启多进程或都线程的方式,在遇到要同时响应成百上千路的连接请求,则无论多线程还是多进程都会严重占据系统资源,降低系统对外界响应效率,而且线程与进程本身还是没有解决IO问题,只是换了一种方式
改进方案:
#很多程序员可能会考虑使用“线程池”。“线程池”旨在减少创建和销毁线程的频率,其维持一定合理数量的线程,并让空闲的线程重新承担新的执行任务。这种技术都可以很好的降低系统开销,都被广泛应用很多大型系统,如websphere、tomcat和各种数据库等。 这种方式确实是好了些,但是还没有解决IO 问题
对应上例中的所面临的可能同时出现的上千甚至上万次的客户端请求,“线程池”或许可以缓解部分压力,但是不能解决所有问题。总之,多线程模型可以方便高效的解决小规模的服务请求,但面对大规模的服务请求,多线程模型也会遇到瓶颈,可以用非阻塞接口来尝试解决这个问题。
三 非阻塞IO(non-blocking IO)
非阻塞IO 是 值 操作系统等数据的那个阶段 变成了非阻塞,而操作系统copy数据的阶段没有变
from socket import *
import time
s=socket(AF_INET,SOCK_STREAM)
s.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
s.bind(('127.0.0.1',8085))
s.listen(5)
s.setblocking(False) #套接字里面的所有阻塞操作都会变成非阻塞
print('starting...')
l=[]
d_l=[]
while True:
try:
print(l)
conn,addr=s.accept()
l.append(conn)
except BlockingIOError: #捕捉 accept收不到数据的时候抛出的异常
for conn in l:
try:
data=conn.recv(1024)
conn.send(data.upper())
except BlockingIOError: #捕捉 recv收不到数据的时候抛出的异常
pass
except ConnectionResetError: #捕捉 客户端突然断开链接的时候抛出的异常
d_l.append(conn)
for j in d_l:
j.close()
l.remove(j)
d_l=[]
服务端
from socket import *
c=socket(AF_INET,SOCK_STREAM)
c.connect(('127.0.0.1',8085)) while True:
cmd=input('ss').strip()
if not cmd:continue
c.send(cmd.encode('utf-8'))
data=c.recv(1024)
print(data.decode('utf-8'))
客户端
但是非阻塞IO模型绝不被推荐。
缺点:
#1. 循环调用recv()将大幅度推高CPU占用率;容易出现卡机情况
#2. 任务完成的响应延迟增大了,因为每过一段时间才去轮询一次accept操作,而任务可能在两次轮询之间的任意时间完成。这会导致整体数据吞吐量的降低。
四 多路复用IO(IO multiplexing) select 模块
from socket import *
import time
import select #自动监听多个套接字 谁好了就可以来取了
server=socket(AF_INET,SOCK_STREAM)
server.bind(('127.0.0.1',8085))
server.listen(5)
print('starting...')
reads_l=[server,]
while True:
r_l,_,_=select.select(reads_l,[],[]) #select.select返回的是 读列表里已经准备好的套接字
print(r_l)
for obj in r_l:
if obj == server:
conn,addr=obj.accept() #obj=server
reads_l.append(conn)
else:
try:
data=obj.recv(1024) #obj=conn
obj.send(data.upper())
except ConnectionResetError: # 捕捉 客户端突然断开链接 造成的异常
pass
服务端
from socket import *
c=socket(AF_INET,SOCK_STREAM)
c.connect(('127.0.0.1',8085)) while True:
cmd=input('ss').strip()
if not cmd:continue
c.send(cmd.encode('utf-8'))
data=c.recv(1024)
print(data.decode('utf-8'))
客户端
select 从流程上分析:效率不如 阻塞IO 的效率高,但是阻塞不能实现并发,
如果select只检测一个套接字,效率肯定不如阻塞IO,但是它可以同时监测多个套接字,而阻塞IO 远远不行。
select 和 非阻塞IO 比较: 非阻塞IO 是自己捕捉信号,自己处理多个套接字的,并且非常占用CPU,而select 是自动捕捉的
select监听的套接字个数不是无限多的
五、selectors模块
select,poll,epoll
epoll模型可以解决套接字个数非常多的情况(因为它的内部检测哪个套接字好了的机制和select不同(select是遍历每个套接字,看有没有好了的,而epoll是 如果哪个套接字好了,就自动跑出来)),但是windows不支持epoll模型
这三种IO多路复用模型在不同的平台有着不同的支持,而epoll在windows下就不支持,好在我们有selectors模块,帮我们默认选择当前平台下最合适的
from socket import *
import selectors #导入selectors后,会根据你的系统 自动选择当前系统下最合适的IO模型
六、socketserver 模块
基于tcp的套接字,关键就是两个循环,一个链接循环,一个通信循环
socketserver模块中分两大类:server类(解决链接问题)和request类(解决通信问题)
import socketserver
class MyTCPhandler(socketserver.BaseRequestHandler): #定义一个类,必须继承
def handle(self): #必须实现handle方法
# print(self.request) # conn
# print(self.client_address) #addr
while True:
try:
data=self.request.recv(1024)
if not data:break
self.request.send(data.upper())
except Exception:
break
self.request.close()
if __name__ == '__main__':
server=socketserver.ThreadingTCPServer(('127.0.0.1',8082),MyTCPhandler)
# server=socketserver.ForkingTCPServer(('127.0.0.1',8082),MyTCPhandler) #Windows没有开进程的方法,会报错
server.allow_reuse_address=True
server.serve_forever()
服务端
from socket import *
client=socket(AF_INET,SOCK_STREAM)
client.connect(('127.0.0.1',8082)) while True:
msg=input('>>: ').strip()
if not msg:continue
client.send(msg.encode('utf-8'))
data=client.recv(1024)
print(data.decode("utf-8"))
客户端
python-day38--IO模型的更多相关文章
- python 浅析IO 模型
协程:遇到IO操作就切换,但是什么时候切回去呢?怎么确定IO操作? 很多程序员可能会考虑使用"线程池"或"连接池"."线程池"旨在减少创建和 ...
- python学习----IO模型
一.IO模型介绍 本文讨论的背景是Linux环境下的network IO. 本文最重要的参考文献是Richard Stevens的"UNIX® Network Programming Vol ...
- Python之IO模型
IO模型介绍 为了更好地了解IO模型,我们需要事先回顾下:同步.异步.阻塞.非阻塞 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞 ...
- 《Python》IO模型
一.IO模型介绍 为了更好地了解IO模型,我们需要事先回顾下: 同步:一件事情做完再做另一件事情 异步:同时做多件事情 阻塞:sleep.input.join.shutdown.get.acquire ...
- Python学习---IO模型1227
1.1. 事件驱动 事件驱动属于一种编程的范式,一种编程的风格,它擅长于处理一些未知的事件,通过绑定一个事件,外界触发后激活这个事情,达到执行某些操作的目的.比如浏览器的onclick()事件 1.2 ...
- python开发IO模型:阻塞&非阻塞&异步IO&多路复用&selectors
一 IO模型介绍 为了更好地了解IO模型,我们需要事先回顾下:同步.异步.阻塞.非阻塞 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非 ...
- Python 之IO模型
阻塞IO模型:以前写的套接字通信都是阻塞型的.通过并发提高效率 非阻塞IO模型: from socket import * # 并不推荐使用,一是消耗cpu资源,二是会响应延迟 server = so ...
- python并发编程之IO模型(Day38)
一.IO模型介绍 为了更好的学习IO模型,可以先看同步,异步,阻塞,非阻塞 http://www.cnblogs.com/linhaifeng/articles/7430066.html#_label ...
- python 全栈开发,Day44(IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)
昨日内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yield,greenlet 遇到IO gevent: 检测到IO,能够使用greenlet实现自动切换,规避了IO阻 ...
- {python之IO多路复用} IO模型介绍 阻塞IO(blocking IO) 非阻塞IO(non-blocking IO) 多路复用IO(IO multiplexing) 异步IO(Asynchronous I/O) IO模型比较分析 selectors模块
python之IO多路复用 阅读目录 一 IO模型介绍 二 阻塞IO(blocking IO) 三 非阻塞IO(non-blocking IO) 四 多路复用IO(IO multiplexing) 五 ...
随机推荐
- ui-grid angularjs
<pre name="code" class="html"><!--ui-grid css--> <link rel=" ...
- 安装Hue后的一些功能的问题解决干货总结(博主推荐)
不多说,直接上干货! 我的集群机器情况是 bigdatamaster(192.168.80.10).bigdataslave1(192.168.80.11)和bigdataslave2(192.168 ...
- 干货:Java多线程详解(内附源码)
线程是程序执行的最小单元,多线程是指程序同一时间可以有多个执行单元运行(这个与你的CPU核心有关). 在java中开启一个新线程非常简单,创建一个Thread对象,然后调用它的start方法,一个 ...
- ACM题目————STL练习之求次数
题目地址:http://acm.nyist.net/JudgeOnline/problem.php?pid=1112 描述 题意很简单,给一个数n 以及一个字符串str,区间[i,i+n-1] 为一个 ...
- 如何使用Unity制作虚拟导览(一)
https://www.cnblogs.com/yangyisen/p/5108289.html Unity用来制作游戏已经是目前市场上的一个发展趋势,而且有越来越多的公司与开发者不断的加入,那么Un ...
- DDR2是什么意思
DDR2DDR2(Double Data Rate 2) SDRAM是由JEDEC(电子设备工程联合委员会)进行开发的新生代内存技术标准,它与上一代DDR内存技术标准最大的不同就是,虽然同是采用了在时 ...
- UVa 12661 Funny Car Racing - spfa
很简单的一道最短路问题.分情况处理赛道的打开和关闭. Code /** * UVa * Problem#12661 * Accepted * Time:50ms */ #include<iost ...
- Python3基础 函数 可变参数,将传进来的参数转成列表
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- Python3基础 file open 打开txt文件并打印出全文
Python : 3.7.0 OS : Ubuntu 18.04.1 LTS IDE : PyCharm 2018.2.4 Conda ...
- 项目管理PV、EV、AC、BAC、EAC、ETC等计算
PV[Planned Value]计划值:应该完成多少工作?[96版的BCWS] EV[Earned Value]挣值:完成了多少预算工作?[96版的BCWP] AC[Actual Cost]实际成本 ...