阻塞IO
用socket 一定会用到accept recv recvfrom这些方法
正常情况下 accept recv recvfrom都是阻塞的
非阻塞IO
如果setblocking(False) 整个程序就变成一个非阻塞的程序了
非阻塞的特点:
没有并发编程的机制
是一个同步的程序
程序不会在某一个连接的recv或者sk的accept上进行阻塞
缺点:
太多while True 高速运行着
大量的占用了CPU导致了资源的浪费
阻塞IO的问题:
一旦阻塞就不能做其他事情了
非阻塞IO的问题:
给CPU造成了很大的负担
import time
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9000))
sk.setblocking(False) # 设置当前的socket server为一个非阻塞IO模型
sk.listen()
conn_l = []
del_l = []
while True:
try:
conn,addr = sk.accept()
conn_l.append(conn) # [conn1,conn2]
except BlockingIOError:
for conn in conn_l: # [conn1,conn2]
try:
conn.send(b'hello')
print(conn.recv(1024))
except (NameError,BlockingIOError):pass
except ConnectionResetError:
conn.close()
del_l.append(conn)
for del_conn in del_l:
conn_l.remove(del_conn)
del_l.clear()
IO多路复用
io多路复用机制
select windows、maclinux
底层是操作系统的轮询
有监听对象个数的限制
随着监听对象的个数增加,效率降低
poll maclinux
底层是操作系统的轮询
有监听对象个数的限制,但是比select能监听的个数多
随着监听对象的个数增加,效率降低
epoll maclinux
给每一个要监听的对象都绑定了一个回调函数
不再受到个数增加 效率降低的影响
import select # 模块 用来操作操作系统中的select(IO多路复用)机制
import socket
sk = socket.socket()
sk.bind(('127.0.0.1',9000))
sk.setblocking(False)
sk.listen()
r_lst = [sk,]
print(sk)
while True:
r_l,_,_ = select.select(r_lst,[],[]) # r_lst = [sk,conn1,conn2,conn3]
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')
except ConnectionResetError:
item.close()
r_lst.remove(item)