阻塞IO(bloking IO)
之前写的socket客户端和服务端收发消息就是阻塞io
非阻塞IO(non-bloking IO)
在之前的socket客户端和服务端收发消息基础上,改变blocking属性来防止未接受到消息的时候阻塞,但是在消息接受的过程中,还是阻塞的
多路IO复用(IO multiplexing)
触发方式:
- 水平触发:只有高电平或者低电平才会触发
- 边缘触发:只有电平发生变化才会触发
方式1:select
select是水平触发机制
多路复用好处:可以同时监听多路链接
select监听多连接
import socket
import select
sk=socket.socket()
sk.bind(("127.0.0.1",8801))
sk.listen(5)
inputs=[sk,]
while True:
r,w,e=select.select(inputs,[],[],5)
for obj in r:#[sk,]
if obj==sk:
conn,add=obj.accept()
print(conn)
inputs.append(conn)
else:
data_byte=obj.recv(1024)
print(str(data_byte,'utf8'))
inp=input('回答%s号客户>>>'%inputs.index(obj))
obj.sendall(bytes(inp,'utf8'))
print('>>',r)
方式2:poll
方式3:epoll
selectors模块
import selectors
import socket
sel = selectors.DefaultSelector()
def accept(sock, mask):
conn, addr = sock.accept() # Should be ready
print('accepted', conn, 'from', addr)
conn.setblocking(False)
sel.register(conn, selectors.EVENT_READ, read)
def read(conn, mask):
try:
data = conn.recv(1000) # Should be ready
if not data:
raise Exception
print('echoing', repr(data), 'to', conn)
conn.send(data) # Hope it won't block
except Exception as e:
print('closing', conn)
sel.unregister(conn)
conn.close()
sock = socket.socket()
sock.bind(('localhost', 8090))
sock.listen(100)
sock.setblocking(False)
sel.register(sock, selectors.EVENT_READ, accept)
print("server.....")
while True:
events = sel.select()#[sock,,conn2]
for key, mask in events:
callback = key.data
callback(key.fileobj, mask)
import socket
import select
sk=socket.socket()
sk.bind(("127.0.0.1",9904))
sk.listen(5)
while True:
r,w,e=select.select([sk,sk],[],[],5)
r=[sk,]
for i in r:
conn,add=i.accept()
print(conn)
print("hello")
print('>>>>>>')