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) 五 ...
随机推荐
- spring mvc @ModelAttribute 每次执行requestmapping前自动执行
在不少应用场景中,我们希望在每次执行requestmapping前自动执行一些操作,比如把某些数据(比如数据字典.系统配置.标准错误号,这在企业应用系统中极为常见)塞到model中供view访问,因为 ...
- CSS3 转换
CSS3 转换 版权声明:未经博主授权,内容严禁转载 什么是转换 转换时使元素改变形状.尺寸和位置的一种效果. 可以对元素应用 2D 或 3D 转换,从而对元素进行旋转.缩放.移动或倾斜. 2D 转换 ...
- 写一个标准宏MIN,输入两个参数,返回较小的
#define MIN(A,B) ((A) <= (B) ? (A) : (B))MIN(*p++, b)会产生宏的副作用 剖析: 这个面试题主要考查面试者对宏定义的使用,宏定义可以实现类似于函 ...
- Java 多线程中的任务分解机制-ForkJoinPool,以及CompletableFuture
ForkJoinPool的优势在于,可以充分利用多cpu,多核cpu的优势,把一个任务拆分成多个“小任务”,把多个“小任务”放到多个处理器核心上并行执行:当多个“小任务”执行完成之后,再将这些执行结果 ...
- Several Service Control Manager Issues (Event ID's 7000, 7009, 7011)
https://answers.microsoft.com/en-us/windows/forum/windows_7-performance/several-service-control-mana ...
- [BZOJ4027][HEOI2015]兔子与樱花 树形dp
Description 很久很久之前,森林里住着一群兔子.有一天,兔子们突然决定要去看樱花.兔子们所在森林里的樱花树很特殊.樱花树由n个树枝分叉点组成,编号从0到n-1,这n个分叉点由n-1个树枝连接 ...
- C# 用Linq查询DataGridView行中的数据是否包含(各种操作)
http://blog.csdn.net/xht555/article/details/38685845 https://www.cnblogs.com/wuchao/archive/2012/12/ ...
- 【TCP/IP详解 卷一:协议】第二十四章 TCP的未来与性能
来到了TCP的最后一个章节,未来与性能.在当时(1991年)的未来,如今已经部分变为现实,部分就只是历史中的实验. 主要内容: 路径MTU的发现与TCP的结合. 长肥管道 和 高速千兆比网络. 窗口扩 ...
- HDU 5887 Herbs Gathering(搜索求01背包)
http://acm.hdu.edu.cn/showproblem.php?pid=5887 题意: 容量很大的01背包. 思路: 因为这道题目背包容量比较大,所以用dp是行不通的.所以得用搜索来做, ...
- python 生成元组
#create a tuple l = [(,), (,), (,)] print(list(zip(*l)))