import socket
from selectors import DefaultSelector, EVENT_READ, EVENT_WRITE
selector = DefaultSelector()
stopped = False
r0 = request(0, "/1")
r1 = request(1, "/2")
t_list = [r0 ,r1]
r0.send(None)
r1.send(None)
def request(index, address):
sock = socket()
sock.connect(address)
def on_read():
print(sock.recv())
t_list[index].send(None)
selector.register(sock.fileno(), EVENT_READ, on_read)
yield # 遇到io,将运行的权利交出去
selector.unregister(sock.fileno())
print(‘完成了‘)
while True:
events = selector.select()
for event_key, event_mask in events:
callback = event_key.data
callback()
代码分析:
1.程序一开始就注册里两个生成器,r0和r1,并且保存在t_list 这个数组里面
并且进行了第一次执行
2.request:
首先定义了一个socket, 并且连接到传递进来的address
并且注册了一个读的事件的回调,并且yield出来,跳出生成器,等待下一次执行
既然已经yield出来,那么生成器下一次执行怎么办,到底需要怎么执行
所以这里的回调就有些意思了,当数据就绪之后,会执行回调
t_list[index].send(None) ,
重新获取到本身这个生成器的引用,然后重新执行一次
等于是当自己的数据已经就绪好了,就会执行自己的回调,自己的回调就是重新调用一下自己,继续激活自己本身这个生成器
3. events = selector.select()当收到读的事件,然后遍历所有的事件,提取出它的回调,
callback = event_key.data callback() 并且执行回调
所以协程的基本原理就是:在遇到 io、阻塞的时候,将运行的权利交出去(例如上面的yield),同时注册唤醒自己的回调;
当阻塞事件完成的时候,通过一个回调来唤醒程序继续往下走,并且返回io事件的值。这句话记下来,考试要考!!!!
原文:https://www.cnblogs.com/wilken/p/14233000.html