tornado源码分析(二)之iostream

在事件驱动模型中,所有任务都是以某个事件的回调函数的方式添加至事件循环中的,如:HTTPServer要从socket中读取客户端发送的request消息,就必须将该socket添加至ioloop中,并设置回掉函数,在回掉函数中从socket中读取数据,并且检查request消息是否全部接收到了,如果没有接收完则需要保存当前的数据,直到读去完为止

iostream的作用是让各组件,不需要与ioloop直接交互,iostream帮助各组件将socket添加至ioloop,并设置回掉函数,读取并保存数据,直到所有数据都接收完为止。有了iostream,httpserver就只需要通过iostream读取数据即可,而不需关心异步读取数据的过程。

iostream同样可以看作一个事件循环,它提供两类事件:读完成、写完成。

iostream是基于ioloop的,创建iostream时必需给定一个文件描述符,iostream将该文件描述符添加至ioloop的io事件中,并设置回调函数(_handle_events),在回掉函数中判断文件描述符是可读,还是可写。

当该文件描述符可读时,iostream从文件描述符中读出数据,并存至自己的数据缓冲中。每次读取到新的数据后,iostream都检查是否触发了自己管理的事件,如:是否读到了某一特定的数据(由read_until、read_until_regex等接口注册),是否读到了足够多的数据(由read_bytes注册)等,如果触发了事件,则调用对应事件的回调函数(异步事件为future,设置future的result即可调用异步事件的回调函数)。

当文件描述符可写时,首先iostream从写缓冲中,读取足量的数据,写入至文件描述符中。其次能进入当前逻辑,说明上一次写入文件描述符的数据已经发送出去了,此时需要逐个检查注册的写事件是否已经完成(各写事件中存储了自己关注的写缓冲区的位置,通过检查该位置判断该事件的数据是否已经发送),如果完成则调用事件的回调函数。

iostream提供了非常多的异步读取数据的接口,read_until,read_bytes,read_unitl_regex等,iostream在同一时间内只能存在一个读事件。

iostream通过write接口添加异步写事件,可以同时存在多个(只要iostream的写缓冲区足够)。每次添加时创建一个future,并且记录该事件的要写的数据在写缓冲区中的位置(加入数据后iostream的_total_write_index),每次有数据发送后根据该位置信息判断是否结束(iostream的_total_write_done_index是否超过了事件的数据的位置)。 

 源码参考:tornado.iostream.IOStream

猜你喜欢

转载自blog.csdn.net/lxyjj/article/details/84713556