HTTPServer在整個框架中最主要的做用是作TCP層和應用層之間的隔離,爲IO和具體應用層搭建了橋樑。python
響應流程圖:web
從功能上看,它最主要作的事情通俗的講就是監聽端口上的動靜(主要是TCP層),當客戶端向服務器某個端口發起請求被其監聽到以後,經過handle_stream來作對應的處理,其中最終調用了HTTP1ServerConnection類的start_serving方法,在這個方法裏最終回調了HTTPServer實現的start_request接口,進入了_ServerRequestAdapter類,在此類初始化的時候判斷HTTPServer類裏的request_callback是否是一個HTTPServerConnectionDelegate(顯然不少時候咱們都定義其繼承類Application),是的話調用此delegate的start_request方法。
服務器
class HTTPServer(TCPServer, httputil.HTTPServerConnectionDelegate): def __init__(self, request_callback, no_keep_alive=False, io_loop=None, xheaders=False, ssl_options=None, protocol=None, decompress_request=False, chunk_size=None, max_header_size=None, idle_connection_timeout=None, body_timeout=None, max_body_size=None, max_buffer_size=None): self.request_callback = request_callback #... def handle_stream(self, stream, address): context = _HTTPRequestContext(stream, address, self.protocol) conn = HTTP1ServerConnection( stream, self.conn_params, context) self._connections.add(conn) conn.start_serving(self) def start_request(self, server_conn, request_conn): return _ServerRequestAdapter(self, server_conn, request_conn) ##httpserver繼承TCPserver中的listen啓動監聽,在啓動過程當中綁定socket,當socket上出現新鏈接請求的時候,啓動handle_stream作對應處理 def listen(self, port, address=""): sockets = bind_sockets(port, addrebind_socketsss=address) self.add_sockets(sockets) def add_sockets(self, sockets): if self.io_loop is None: self.io_loop = IOLoop.current() for sock in sockets: self._sockets[sock.fileno()] = sock add_accept_handler(sock, self._handle_connection, io_loop=self.io_loop) def _handle_connection(self, connection, address): #.... self.handle_stream(stream, address) ##############class HTTP1ServerConnection(object): def start_serving(self, delegate): assert isinstance(delegate, httputil.HTTPServerConnectionDelegate) self._serving_future = self._server_request_loop(delegate) self.stream.io_loop.add_future(self._serving_future, lambda f: f.result()) @gen.coroutine def _server_request_loop(self, delegate): #... conn = HTTP1Connection(self.stream, False, self.params, self.context) request_delegate = delegate.start_request(self, conn) ###########真正將客戶端請求回調到對應的handler的地方 class _ServerRequestAdapter(httputil.HTTPMessageDelegate): def __init__(self, server, server_conn, request_conn): #... if isinstance(server.request_callback, httputil.HTTPServerConnectionDelegate): self.delegate = server.request_callback.start_request( server_conn, request_conn)
還記得這個例子麼:
app
if __name__=="__main__": tornado.options.parse_command_line() #實例了一個Application,其中有兩個RequestHandler對:"/" -- IndexHandler,'/poem' -- PoemPageHandler app = tornado.web.Application( handlers=[(r"/", IndexHandler), (r'/poem', PoemPageHandler)], template_path=os.path.join(os.path.dirname(__file__), "templates") ) http_server = tornado.httpserver.HTTPServer(app) http_server.listen(options.port) tornado.ioloop.IOLoop.instance().start()
用戶定義好了兩個RequestHandler,分別對應輸入流裏的」/「 和‘/poem‘,將此元組初始化Application,並將其做爲參數傳遞給http_server, http_server啓動監聽,當監聽到客戶端傳來的輸入流,截取其中的header,並將其轉入Application的start_request處理。框架
def start_request(self, server_conn, request_conn): # Modern HTTPServer interface return _RequestDispatcher(self, request_conn) ###then 咱們來到這個具體實現的類: class _RequestDispatcher(httputil.HTTPMessageDelegate): def headers_received(self, start_line, headers): self.set_request(httputil.HTTPServerRequest( connection=self.connection, start_line=start_line, headers=headers)) if self.stream_request_body: self.request.body = Future() return self.execute() def _find_handler(self): app = self.application handlers = app._get_host_handlers(self.request) if not handlers: self.handler_class = RedirectHandler self.handler_kwargs = dict(url="%s://%s/" % (self.request.protocol, app.default_host)) return for spec in handlers: match = spec.regex.match(self.request.path) if match: self.handler_class = spec.handler_class self.handler_kwargs = spec.kwargs if spec.regex.groups: if spec.regex.groupindex: self.path_kwargs = dict( (str(k), _unquote_or_none(v)) for (k, v) in match.groupdict().items()) else: self.path_args = [_unquote_or_none(s) for s in match.groups()] return if app.settings.get('default_handler_class'): self.handler_class = app.settings['default_handler_class'] self.handler_kwargs = app.settings.get( 'default_handler_args', {}) else: self.handler_class = ErrorHandler self.handler_kwargs = dict(status_code=404) def execute(self): if not self.application.settings.get("compiled_template_cache", True): with RequestHandler._template_loader_lock: for loader in RequestHandler._template_loaders.values(): loader.reset() if not self.application.settings.get('static_hash_cache', True): StaticFileHandler.reset() self.handler = self.handler_class(self.application, self.request, **self.handler_kwargs) transforms = [t(self.request) for t in self.application.transforms] if self.stream_request_body: self.handler._prepared_future = Future()