wiki的中文定义:Reactor模式是事件驱动的,有一个或多个并发输入源,有一个Service Handler,有多个Request Handler,这个Service Handler会同步的将输入的请求(Event)多路复用的分发给相应的Request Handler。
从上述文字中我们可以看出以下关键点:
- 事件驱动(event handling)
- 可以处理一个或多个输入源(one or more inputs)
- 通过Service Handler同步的将输入事件(Event)采用多路复用分发给相应的Request Handler(多个)处理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dqMXsBTi-1590139303282)(C:\Users\andyhkmo\Pictures\Saved Pictures\pic3.png)]
单Reactor单线程模式如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uC8us57g-1590139303285)(C:\Users\andyhkmo\Pictures\Saved Pictures\pic4.png)]
简单代码如下
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server_socket.bind(('', 2007))
server_socket.listen(5)
# serversocket.setblocking(0)
poll = select.poll() # epoll() should work the same
connections = {}
handlers = {}
def handle_input(socket, data):
socket.send(data) # sendall() partial?
def handle_request(fileno, event):
if event & select.POLLIN:
client_socket = connections[fileno]
data = client_socket.recv(4096)
if data:
handle_input(client_socket, data)
else:
poll.unregister(fileno)
client_socket.close()
del connections[fileno]
del handlers[fileno]
def handle_accept(fileno, event):
(client_socket, client_address) = server_socket.accept()
print "got connection from", client_address
# client_socket.setblocking(0)
poll.register(client_socket.fileno(), select.POLLIN)
connections[client_socket.fileno()] = client_socket
handlers[client_socket.fileno()] = handle_request
poll.register(server_socket.fileno(), select.POLLIN)
handlers[server_socket.fileno()] = handle_accept
while True:
events = poll.poll(10000) # 10 seconds
for fileno, event in events:
handler = handlers[fileno]
handler(fileno, event)
最基本的单线程Reactor模型,程序的核心是事件循环,通过handlers转发到各个函数中去。
muduo是基于非阻塞的IO和事件驱动的网络库。
muduo的整体结构是one loop per thread+threadpool。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nZqaGYcF-1590139303286)(C:\Users\andyhkmo\Pictures\Saved Pictures\pic9.png)]
muduo的事件驱动都是通过一个EventLoop来完成的。EventLoop一直处在事件循环中,通过IO复用机制poll/epoll回调激活的事件。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-39RZJVEe-1590139303288)(C:\Users\andyhkmo\Pictures\Saved Pictures\pic5.png)]
而muduo的Reactor主要由三部分组成,EventLoop、Poller、Channel。
EventLoop
即IO线程中的事件循环.它能确保所有注册的事件都在EventLoop
对象所在的线程中执行,不用考虑事件的并发。它是线程安全的,且允许其他线程往EventLoop
里面塞东西。
Poller
是IO multiplexing
的封装,它是EventLoop
的组成,与EventLoop
的生命期相当,为EventLoop
提供poll()
方法。
Channel
每个Channel
对象自始至终只负责一个文件描述符(fd)
的IO
事件分发,但它不拥有这个fd
,也不会在析构的时候关闭这个fd
。每个Channel对象自始至终只属于一个EventLoop
,因此每个Channel
对象都只属于某一个IO线程。 Channel
会把不同的IO事件分发为不同的回调, 例如ReadCallback
、 WriteCallback
等。
EventLoop的时序图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LTmuUSrj-1590139303291)(C:\Users\andyhkmo\Pictures\Saved Pictures\pic6.png)]
具体实现代码如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VW0kROkN-1590139303292)(C:\Users\andyhkmo\AppData\Roaming\Typora\typora-user-images\1590033396599.png)]
由于muduo整体架构one loop per thread + threadpool的架构,也可以说是一个主EventLoop和EventLoopPool的方式。
主EventLoop管理Acceptor,主要是listen和accept新的连接,然后由EventLoopPool去处理新Channel的读写事件。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2s5ypFkL-1590139303293)(C:\Users\andyhkmo\Pictures\Saved Pictures\pic8.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mojSBfzK-1590139303294)(C:\Users\andyhkmo\AppData\Roaming\Typora\typora-user-images\1590040905144.png)]
待续:muduo中的线程安全日志的实现,异步日志。