对于来自单个客户端套接字的连接,我的 http 服务器中的 http 数据是否会出现乱序?

问题描述 投票:0回答:1

我正在实现我自己的http服务器:

import socket
import threading
import queue
import ssl
from manipulator.parser import LineBuffer,LoggableHttpRequest

class SocketServer:
    """
        Basic Socket Server in python
    """

    def __init__(self,host,port,max_threads,ssl_context:ssl.SSLContext=None):
        print("Create Server For Http")        

        self.host = host
        self.port = port
        self.server_socket = self.initSocket()
        self.max_threads = max_threads
        self.request_queue = queue.Queue()   

        self.ssl_context=None
        if(ssl_context != None):
            print("Initialise SSL context")        
            self.ssl_context = ssl_context

    def initSocket(self):
        return socket.socket(socket.AF_INET, socket.SOCK_STREAM)

   
    def __accept(self):
        self.server_socket.listen(5)
        while True:
            try:
                client_socket, client_address = self.server_socket.accept()
                
                if self.ssl_context is not None :
                    print(self.ssl_context)
                    client_socket = self.ssl_context.wrap_socket(client_socket, server_side=True)

                self.request_queue.put((client_socket, client_address))
            except:
                print("Error Occured")


    def __handle(self):
        while True:
            client_socket, address = self.request_queue.get()
            print("Address",address)
            
            try:
                # Read HTTP Request
                # Log Http Request
                # Manipulate Http Request
                # Forward or respond

                buffer = LineBuffer()
                request =  HttpRequest(self.db)

                buffer.pushData(client_socket.recv(2048))
                line = buffer.getLine()
                if(line is not None):
                    request.parse(line)

                content = '<html><body>Hello World</body></html>\r\n'.encode()
                headers = f'HTTP/1.1 200 OK\r\nContent-Length: {len(content)}\r\nContent-Type: text/html\r\n\r\n'.encode()
                client_socket.sendall(headers + content)
          
            finally:
                client_socket.shutdown(socket.SHUT_RDWR)
                client_socket.close()
                self.request_queue.task_done()


    def __initThreads(self):
        for _ in range(self.max_threads):
            threading.Thread(target=self.__handle, daemon=True).start()


    def start(self):
        self.server_socket.bind((self.host, self.port))
        self.__initThreads()
        self.__accept()

我这样做的原因是我想尽快记录和分析传入的 httpo 请求。另外,许多第 3 方库确实需要我想避免的 C 绑定。

到目前为止,我制作了一个行分块器,将请求分成 :

class LineBuffer:

    def __init__(self):
        self.buffer = b''
    
    def pushData(self,line):
        self.buffer += str.encode(line)
    
    def getLine(self):
        if  b'\r\n' in self.buffer:
            line,sep,self.buffer = self.buffer.partition(b'\r\n')
            return line+sep
        return None

我想解析每一行并将其序列化为一个表示 http 请求的对象,我可以以流式传输方式进一步传输它:

class HttpRequest:
    
    def __init__(self,db):
        self.headers={} #ParsedHeaderrs
        self.body="" #Http Body
        self.version=None
        self.method=None
        self.id=None
        self.raw=""

class HttpParser:

    def __init__(self,db):
        self.db = db
        self.currentRequest=None
    
    def parse(line):
        # do parsing here
        return

我最担心的是一个客户端会发送2个请求的场景:

要求1:

GET / HTTP/1.1\r\n
HOST lala1.com \r\n

要求2:

POST /file HTTP/1.1\r\n
HOST lala2.com \r\n
\r\n
Qm9QUVM5NDMuLnEvXVN7O2E=
fDMpQjcpOlFodClgOGUzYQ==
NVgvNipmU1d3YFgtLFUhQiM=
MiZwSk0zKno9TkVxNyZFL3s=
NEhGJXZ7OGciOE8mYF5JNA==
dVlJLzpdKlUjXl4tcEpufQ==
XVgiXCdjQyckMjY/Ikt6Rw==
alksJlZ+XHFzQSYqaHlHIztt
YiRnPjdye0gvanV3ZGxaZkI=
MjgwTX0uYHw6M295RS52UDM=
YU0yQ2dQLmJUQVpCNS89PWJB
Ti10MHJBTjAqUFUlIU0sMyRN

但是我的服务器收到的顺序是:

GET / HTTP/1.1\r\n
POST /file HTTP/1.1\r\n
HOST lala1.com \r\n
\r\n\r\nQm9QUVM5ND
HOST lala2.com \r\n
MuLnEvXVN7O2E=
fDMpQjcpOlFodClgOGUzYQ==
NVgvNipmU1d3YFgtLFUhQiM=
MiZwSk0zKno9TkVxNyZFL3s=
NEhGJXZ7OGciOE8mYF5JNA==
dVlJLzpdKlUjXl4tcEpufQ==
XVgiXCdjQyckMjY/Ikt6Rw==
alksJlZ+XHFzQSYqaHlHIztt
YiRnPjdye0gvanV3ZGxaZkI=
MjgwTX0uYHw6M295RS52UDM=
YU0yQ2dQLmJUQVpCNS89PWJB
Ti10MHJBTjAqUFUlIU0sMyRN
\r\n

我的情况可行吗?还是tcp套接字自己处理数据顺序?

python http sockets server tcp
1个回答
0
投票

HTTP/1 请求和响应是序列化的,即同一 TCP 连接内不存在多个请求或响应的交错,并且响应必须与请求具有相同的顺序并位于同一 TCP 连接上。对于 HTTP/2,这是不同的,但您的代码只需要 HTTP/1。

© www.soinside.com 2019 - 2024. All rights reserved.