TCPSever建立socket连接后,将socket包装成IOStream类,然后调用self.handle_stream()函数处理
tornado.httpserver.HTTPServer 继承了TCPSever,实现了handle_stream()方法。
HTTPSever通过两个类来实现从socket中读取http请求消息:tornado.http1connection.HTTP1ServerConnection与tornado.http1connection.HTTP1Connection
HTTP1ServerConnection,实现一个死循环,用于驱动HTTP1Connection。
HTTP1Connection从socket中读取数据,按照http消息的格式进行解析,生成对应保存header、body信息的python类,之后调用HTTPSever给它的处理对象进行处理。
具体过程如下
class HTTPServer(TCPServer,Configurable,httputil.HTTPServerConnectionDelegate): def __init__(self, application): #http服务器处理http消息的部分,在下一节分析 self.delegate = _CallableAdapter(application) def handle_stream(self, stream, address): context = _HTTPRequestContext(stream, address, self.protocol, self.trusted_downstream) #将连接包装成一个HTTP1ServerConnection对象,该对象提供了从socket中读取并解析http消息的函数start_serving conn = HTTP1ServerConnection(stream, self.conn_params, context) self._connections.add(conn) #开始从socket中读取数据,并且传入用于处理解析出来的header、body的类 conn.start_serving(self.delegate) class HTTP1ServerConnection(object): def start_serving(self, delegate): self._serving_future = self._server_request_loop(delegate) @gen.coroutine def _server_request_loop(self, delegate): #死循环,不断的从socket中读取数据,每次循环会读取一个完整的http消息 while True: conn = HTTP1Connection(self.stream, False, self.params, self.context) request_delegate = delegate.start_request(self, conn) ret = yield conn.read_response(request_delegate) class HTTP1Connection(httputil.HTTPConnection): def read_response(self, delegate): if self.params.decompress: delegate = _GzipMessageDelegate(delegate, self.params.chunk_size) return self._read_message(delegate) @gen.coroutine def _read_message(self, delegate): #异步读取http消息头部 header_future = self.stream.read_until_regex( b"\r?\n\r?\n", max_bytes=self.params.max_header_size) header_data = yield header_future #解析http消息头部 start_line, headers = self._parse_headers(header_data) #调用上层即HTTPServer处理解析出来的http消息头部,该处理也是异步的 header_future = delegate.headers_received(start_line, headers) if header_future is not None: yield header_future ...... #会根据头部的数据判断是否有body存在 具体过程略 #如果有body部分则继续读取body部分并处理,同样也是异步的读,然后调用上层HTTPServer处理,具体过程略 if not skip_body: body_future = self._read_body(start_line.code if self.is_client else 0, headers, delegate) yield body_future