IO多路复用
1,local:同一线程内,数据是共享的,loca可以产生线程ID,使数据隔离:
import time import random from threading import local,Thread loc = local() def func2(): global loc print(loc.name,loc.age) def func(name,age): global loc loc.name = name loc.age = age time.sleep(random.random()) func2() Thread(target=func,args=('liming',22)).start() Thread(target=func,args=('lijing',42)).start()
2.
同步:一件事情做完再做另一件
异步:同时做多件事情
阻塞:sleep,input,join,shutdown,wait,acquire,get
recv,recvfrom,accept
非阻塞:setblocking(False)
3网络IO模型
socket
用socket 一定会用到accept,recv,reccvfrom这些方法
正常情况下,recv,recvfrom,accept都是阻塞的
如果setblocking(False)这个程序就变成非阻塞
阻塞IO:recv做了哪些事情:
阻塞IO的recv,
wait for data阶段 阻塞
copy data 阶段 阻塞
非阻塞IO:
没有并发编程的机制
同步程序
非阻塞的特点
程序不会在某一个连接的recv或者sk的accept上进行阻塞
获得时间做信息的收发
非阻塞IO问题:占用cpu大量资源,给cpu造成很大的负担
阻塞IO问题:一旦阻塞,程序不往下执行
同时因为while True 高速运行着
大量的占用了CPU导致资源的浪费
import socket sk = socket.socket() sk.bind(('192.168.16.33',8088)) sk.setblocking(False) #设置当前的socket server 为一个非阻塞IO模型 sk.listen() conn_1 = [] del_1 = [] while True: try: conn,addr = sk.accept() conn_1.append(conn) except BlockingIOError: for conn in conn_1: try: conn.send(b'ok') print(conn.recv(1024)) #收到对面的消息 except (NameError,BlockingIOError): pass except ConnectionAbortedError: conn.close() del_1.append(conn) for del_conn in del_1: conn_1.remove(del_conn) del_1.clear()
import socket sk = socket.socket() sk.connect(('192.168.16.33',8088)) for i in range(1000000): print(sk.recv(1024)) sk.send(b'hello') sk.close()
4:IO多路复用:
IO阻塞一个没有消息,后面全部阻塞
IO非阻塞,即使没有消息,还在循环,永远在就绪与运行之间切换,能够最大限度利用cpu,但是不排除过度利用
IO多路复用,有消息就运行,没有就停止,操作系统提供的,一个代理,帮助监听网络IO对象,监听对象的读事件,写事件,特殊条件事件
异步IO:等待数据阶段和拷贝数据阶段都不需要用户处理,所有的操作都由操作系统完成,拷贝数据阶段,只有IO异步不需要阻塞
谁提供了你一个IO多路复用的机制?
操作系统提供的,python只是使用者
import select #模块 #用来操作操作系统中的select(IO多路复用)机制 # def select(rlist,wlist,xlist,timeout=None) 监听:读,写,特殊条件 import socket sk = socket.socket() sk.bind(('192.168.16.33',8088)) sk.setblocking(False) sk.listen() r_lst = [sk,] while True: r_l,_,_ = select.select(r_lst,[],[]) for item in r_l: if item is sk: conn,addr = sk.accept() r_lst.append(conn) else: try: print(item.recv(1024)) item.send(b'hello bb') except ConnectionResetError: item.close() r_lst.remove(item)
import socket sk = socket.socket() sk.connect(('192.168.16.33',8088)) for i in range(1000000): sk.send(b'hello') print(sk.recv(1024)) sk.close()
IO多路复用机制:
select windows,mac\linux
底层是操作系统轮询
有监听对象个数的限制
随着监听对象的个数增加,效率降低
poll
底层是操作系统轮询
有监听对象个数的限制但是比select能监听的个数多
随着监听对象的个数增加,效率降低
epoll
给每一个要监听的对象都绑定了一个回调函数
不再受到个数增加,效率降低的影响
同点:
都是起到代理作用