![](https://csdnimg.cn/release/download_crawler_static/10709129/bga.jpg)
而当其它模块要连接到外部网络时,应该调用 start_connection 函数,这个
函数将把网络插口添加到另一个字典 single_sockets 中,当然,使用了
SingleSocket 对象对其进行了一定程度的包装。从后面的分析可以看到,这个
SingleSocket 对象的主要功能是对输出的 数据进行了一定的缓冲,并在不会阻塞
的情况下把这些数据实际得写到 socket 中。start_connection 需要传入的处理对
象是必须包含 data_came_in 而可以不包含 external_connection_made 的对象。
在 start_listening 和 start_connection 中都用到了 poll 对象,这是系统提
供的一个提供轮询机制的模块,使用文件描述符作 为参数,可以得到相应的事件
(即该文件描述符对应的插口有数据流入或者留出等),而在这两个函数中,都调用
了 poll 的注册函数,方便后面的 poll 轮询 操作。
需要注意的是,在上面的这些函数被执行后,网络连接还是不会被处理,因为
虽然打开了相应的网络插口,也注册了相应的处理对象,但是整个的轮询机制还没
有建 立起来。直到 listen_forever 函数被调用后,这个机制才真正得建立起来。
这个函数的主体就是一个无限的 while 循环,只有 doneflag 这个事件可以被用来
中止这个循环。它首先做的事情是从添加的任务 funcs 寻找最近要执行的任务的时
间,并与当前时间相减,计算出 period,然后用 poll 轮询这么长的时间,这样做
就可以保证轮询结束后不会耽误外部任务过久。轮询到的结果返回在 events 里,
这是一个列表,它的元素是以文件描述符 和事件所组成的二元组。接下来就是根
据时间的情况,把需要马上执行的外部任务都执行了,_make_wrapped_call 的主
要作用就是执行外部任 务,只是给它们增加一些意外处理的保护代码。执行完这
些外部任务后,调用_close_dead 关闭不活跃的网络连接,接下来就是使用
_handle_events 来处理前面的 poll 搜集到的网络事件了。
_handle_events 的主体是一个 for 循环,检查每一个 sock 和它对应的
event。首先看它是在 serversockets 字典中还是在 single_sockets 字典中,如