事件驱动模型
事件驱动编程,是一种编程范式。这里程序的执行流由外部事件来决定。它的特点是包含一个循环,当外部事件发生时,使用回调机制来触发相应的处理。
另外2种常见的编程范式是(单线程)同步以及多线程编程
IO模型
同步IO(synchronous),异步IO(asynchronous),阻塞IO(blocking) 和非阻塞IO(non-blocking) 都是独立的,不一起出现
5种IO模型如下:
-blocking IO
-nonblocking IO
-IO multiplexing(IO多路复用)
-signal driven IO
-asynchronous IO
blocking IO (阻塞IO)
在linux 中,默认情况下所有的socket 都是blocking IO,阻塞IO 只发生了一次系统调用
实例:
-server 端
import socket
sk=socket.socket()
sk.bind(("127.0.0.1",8080))
sk.listen(5)
while 1:
conn,addr=sk.accept()
while 1:
conn.send("hello client".encode("utf8"))
data=conn.recv(1024)
print(data.decode("utf8"))
-client端
import socket
sk=socket.socket()
sk.connect(("127.0.0.1",8080))
while 1:
data=sk.recv(1024)
print(data.decode("utf8"))
sk.send(b"hello server")
非阻塞IO
缺点:不能及时收发消息,系统调用太多次
实例
-server 端
import time
import socket
sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
sk.bind((‘127.0.0.1‘,6667))
sk.listen(5)
sk.setblocking(False) #此代码代表不会一值等待连接(如上图)
print (‘waiting client connection .......‘)
while True:
try:
connection,address = sk.accept() # 进程主动轮询
print("+++",address)
client_messge = connection.recv(1024)
print(str(client_messge,‘utf8‘))
connection.close()
except Exception as e:
print (e)
time.sleep(4)
-client 端
import time
import socket
sk = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
while True:
sk.connect((‘127.0.0.1‘,6667))
print("hello")
sk.sendall(bytes("hello","utf8"))
time.sleep(2)
break
IO multiplexing(IO多路复用)
IO多路复用实现并发的方法:
1)select 可跨平台使用,但是监听连接数最大为1024
2) poll
3) epoll (推荐使用):效率高,最好的实现方式
实例一:
-server 端
import socket
import select
sk=socket.socket()
sk.bind(("127.0.0.1",9904))
sk.listen(5)
inp=[sk,]
while True:
r,w,e=select.select(inp,[],[],5) #[sk,conn]
#inp是指输入内容,第一个[]是输出,第二个[]是报错,数字5是每隔5秒监听一次(可自己设置秒数)
for i in r:#[sk,]
conn,add=i.accept()
print(conn)
print("hello")
inp.append(conn)
print(‘>>>>>>‘)
-client 端
import socket
sk=socket.socket()
sk.connect(("127.0.0.1",9904))
while 1:
inp=input(">>").strip()
sk.send(inp.encode("utf8"))
data=sk.recv(1024)
print(data.decode("utf8"))
select 是水平触发
实例二:
server 端
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)
client 端
import socket
sk = socket.socket()
sk.connect((‘127.0.0.1‘, 8801))
while True:
inp = input(">>>>")
sk.sendall(bytes(inp, "utf8"))
data = sk.recv(1024)
print(str(data, ‘utf8‘))
异步IO(asynchronous IO)
异步IO:全程无阻塞