博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

目标:

从创建HTTPServer,从TCP连接中读取http请求消息,解析请求消息,并打印

 

server端

# -*- coding: utf-8 -*-
from tornado.ioloop import IOLoop
from tornado.http1connection import HTTP1Connection
from tornado.tcpserver import TCPServer

class TestHttp1Connection(TCPServer):
    #TCPServer建立一个来自客户端的连接后,包装成iostream,然后调用该函数处理
    def handle_stream(self, stream, address):

        handle_data = self.HandleHttp1Data()
        
        #实例化从tcp链接中读取http消息的类,然后读取请求消息
        h1con = HTTP1Connection(stream, is_client=False)
        h1con.read_response(handle_data)
    
    #处理HTTP1Connection读取到的http数据
    class HandleHttp1Data(object):
        #当HTTP1Connection读取到头部数据,并解析为start_line, headers后调用该函数
        def headers_received(self, start_line, headers):
            self.chunk_numbers = 0
            self.chunks = []
            print('start_line', start_line)
            print('type of headers', type(headers))
            for i in headers.keys():
                print(i, ':', headers[i])
        
        #当HTTP1Connection读取到请求数据后调用该函数(请求数据可能是分片到达的)
        def data_received(self, chunk):
            self.chunk_numbers += 1
            self.chunks.append(chunk)
        
        #当请求数据的所有分片到达后调用
        def finish(self):
            print('请求数据已经全部接受完毕:', ''.join([i.decode('utf-8') for i in self.chunks]))
        
        def on_connection_close(self):
            print('TCP连接断开')
    

if __name__ == '__main__':
    test = TestHttp1Connection()
    test.listen(8888)
    IOLoop.instance().start()

客户端:

# -*- coding: utf-8 -*-

from socket import *

HOST ='localhost'
PORT = 8888
ADDR = (HOST,PORT)

http_message = ['GET /form.html HTTP/1.1\r\n', 
                'Accept: image/gif,image/jpeg,*/*\r\n',
                'Accept-Language: zh-cn\r\n',
                'Connection: Keep-Alive\r\n',
                'Host: localhost\r\n',
                'User-Agent: Mozila/4.0(compatible;MSIE5.01;Window NT5.0)\r\n',
                'Accept-Encoding: gzip,deflate\r\n\r\n',
                'username=jinqiao&password=1234',]

tctimeClient = socket(AF_INET,SOCK_STREAM)
tctimeClient.connect(ADDR)
for m in http_message:
    tctimeClient.send(m.encode())
tctimeClient.close()

输出:

start_line RequestStartLine(method='GET', path='/form.html', version='HTTP/1.1')
type of headers <class 'tornado.httputil.HTTPHeaders'>
Accept : image/gif,image/jpeg,*/*
Accept-Language : zh-cn
Connection : Keep-Alive
Host : localhost
User-Agent : Mozila/4.0(compatible;MSIE5.01;Window NT5.0)
Accept-Encoding : gzip,deflate
请求数据已经全部接受完毕: username=jinqiao&password=1234

 

tornado关键源码:

tornado.httpserver.HTTPServer.handle_stream()   与TCPServer的接口

tornado.httpserver._ServerRequestAdapter()  httpserver用来处理HTTP1Connection接收并解析的http数据

tornado.http1connection.HTTP1Connection  tornado用来从TCP连接中读取http消息的类