一、 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模型的更多相关文章

  1. python 浅析IO 模型

    协程:遇到IO操作就切换,但是什么时候切回去呢?怎么确定IO操作? 很多程序员可能会考虑使用"线程池"或"连接池"."线程池"旨在减少创建和 ...

  2. python学习----IO模型

    一.IO模型介绍 本文讨论的背景是Linux环境下的network IO. 本文最重要的参考文献是Richard Stevens的"UNIX® Network Programming Vol ...

  3. Python之IO模型

    IO模型介绍 为了更好地了解IO模型,我们需要事先回顾下:同步.异步.阻塞.非阻塞 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非阻塞 ...

  4. 《Python》IO模型

    一.IO模型介绍 为了更好地了解IO模型,我们需要事先回顾下: 同步:一件事情做完再做另一件事情 异步:同时做多件事情 阻塞:sleep.input.join.shutdown.get.acquire ...

  5. Python学习---IO模型1227

    1.1. 事件驱动 事件驱动属于一种编程的范式,一种编程的风格,它擅长于处理一些未知的事件,通过绑定一个事件,外界触发后激活这个事情,达到执行某些操作的目的.比如浏览器的onclick()事件 1.2 ...

  6. python开发IO模型:阻塞&非阻塞&异步IO&多路复用&selectors

    一 IO模型介绍 为了更好地了解IO模型,我们需要事先回顾下:同步.异步.阻塞.非阻塞 同步(synchronous) IO和异步(asynchronous) IO,阻塞(blocking) IO和非 ...

  7. Python 之IO模型

    阻塞IO模型:以前写的套接字通信都是阻塞型的.通过并发提高效率 非阻塞IO模型: from socket import * # 并不推荐使用,一是消耗cpu资源,二是会响应延迟 server = so ...

  8. python并发编程之IO模型(Day38)

    一.IO模型介绍 为了更好的学习IO模型,可以先看同步,异步,阻塞,非阻塞 http://www.cnblogs.com/linhaifeng/articles/7430066.html#_label ...

  9. python 全栈开发,Day44(IO模型介绍,阻塞IO,非阻塞IO,多路复用IO,异步IO,IO模型比较分析,selectors模块,垃圾回收机制)

    昨日内容回顾 协程实际上是一个线程,执行了多个任务,遇到IO就切换 切换,可以使用yield,greenlet 遇到IO gevent: 检测到IO,能够使用greenlet实现自动切换,规避了IO阻 ...

  10. {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) 五 ...

随机推荐

  1. linux基础命令---chattr

    chattr 改变文件的属性,这个命令只有超级用户才能使用.这个指令适用于ext2.ext3.ext4.xfs.ubifs.reiserfs.jfs系统. 此命令的适用范围:RedHat.RHEL.U ...

  2. Web前端学习笔记之安装和使用PhantomJS

    0x00 安装PhantomJS(linux环境安装) 将PhantomJS下载在/usr/local/src/packet/目录下(这个看个人喜好) 操作系统:CentOS 7 64-bit 1.下 ...

  3. Python3 itchat实现微信定时发送群消息

    Python3 itchat实现微信定时发送群消息 一.简介 1,使用微信,定时往指定的微信群里发送指定信息. 2,需要发送的内容使用excel进行维护,指定要发送的微信群名.时间.内容. 二.py库 ...

  4. spring MVC @Resource不支持Lazy加载及解决方法

    今天迁一系统时发现有个bean使用@Resource注入了另外一个bean,这个被注入的bean是将被deprecated的类,而且只有一两个功能使用到,为了先调整进行测试,增加了@Lazy注解,启动 ...

  5. Ubuntu18.04安装Openssl-1.1.1

    1.查看版本 Ubuntu的版本是18.04.使用openssl version命令查看openssl版本,可以看到Ubuntu自带了openssl-1.1.0版本,因此安装新版本需要替换旧版本. 2 ...

  6. 在一个activity中销毁指定activity

    通过静态变量的方法: 1.在Aactivity中设置一个Activity静态变量 static Activity activity; 2.在onCreate中: activity=this: 3.在B ...

  7. 命令模式(head first 设计模式5)

    一.命令模式定义 命令大家都不会陌生,那么在开始命令模式之前,可以想象一下生活中的命令模式的特点: 如老板命令你完成一个OA项目是一个命令,接着看看其特点: 1.在上面的命令中,命令的执行者肯定是聪明 ...

  8. UVa 1626 括号序列(矩阵连乘)

    https://vjudge.net/problem/UVA-1626 题意: 输入一个由 "(" . ")" . "[" . " ...

  9. UVa 11212 编辑书稿(dfs+IDA*)

    https://vjudge.net/problem/UVA-11212 题意:给出n个自然段组成的文章,将他们排列成1,2...,n.每次只能剪切一段连续的自然段,粘贴时按照顺序粘贴. 思路:状态空 ...

  10. spring cloud kubernetes之serviceaccount permisson报错

    spring boot项目引用spring-cloud-starter-kubernetes <dependency> <groupId>org.springframework ...