Yifei Kong

Jun 22, 2018

curio 的 http 库 asks 代码解析

asks 是 Python 的异步框架 curio 中的 一个 http 库。

init.py

init 函数,初始化 curio 或者 trio 库

auth.py

auth 相关函数

base_funcs.py

asks.request 函数,创建一个session,然后做请求,之后再丢弃掉这个session

cookie_utils.py

CookieTracker类

对外的方法主要有两个 get_additional_cookies 用于获取域名对应的cookie,_store_cookies 用于添加cookie

errors.py 抛出的异常的类

req_structs.py

SocketQ

这是一个 socket 的连接池。

使用一个deque作为存储,实际上相当于又模拟了一个字典{netloc => socket}(思考:为什么不使用OrderedDict呢?) 是deque的子类。index返回指定hostloc对应的index。pull弹出指定index的socket。__contains__遍历看是否包含对应的socket

CaseIncesitiveDict 对大小写不敏感的词典

request.py

Request 类

make_request 方法。hconnection定义和使用的地方相距太远了。cookie的生成应该使用join。之后调用_request_io 发送请求

_request_io 调用 首先掉用_send, 然后调用_catch_response

_catch_response 调用recv_event

_recv_event 不断调用 _async_lib.recv(self.sock, 10000) 从而不断产生数据,知道读完为之

session 类

request 调用 grab_connection 获取一个socket,然后把这个socket交给Request对象 grab_connection 调用 checkout_connection 获得一个socket或者,调用make_connection产生一个新的socket,注意其中有一个奇怪的 await sleep(0),可能意思是把循环交回给event loop

make_connection 调用_connect 方法,并把host和port作为属性写到socket上

session 中有两个SocketQ的类,conn_pool, checked_out_sockets 分别用来保存已连接未使用的socket和正在使用中的socket

Asks 的连接池

如果使用代理的话

curio 的网络通信

首先,需要引入curio.socket 而不是使用内置的socket TCP通信,使用sock.bind/listen/accept等建立服务器,使用recv和sendall发送接收消息 UDP通信,使用recvfrom和sendto函数通信

作为客户端使用curio.open_connection 打开到服务器的链接,其中ssl=True打开的是HTTPS连接诶

对于其他要使用ssl的情况,应该使用curio.ssl而不是标准库的ssl

curio.network.

ssl.wrap_socket 不支持server_hostname sslcontext.wrap_socket 支持

不要把 proxies 传递给request 对象