实现 HTTPServer

简单开始

import selectors
import socket

tcp_socket = socket.socket()

tcp_socket.bind(("127.0.0.1",8888))

tcp_socket.listen(5)

def my_accept(sock,mask):
    new_sock,add = sock.accept()
    data = new_sock.recv(1024)
    print(data)

selector = selectors.DefaultSelector()

selector.register(tcp_socket,selectors.EVENT_READ,my_accept)

while True:
    print("服务器开始运行")
    events = selector.select()
    for key,mask in events:
        callback = key.data
        callback(key.fileobj,mask)

使用selectors实现并发和管理socket

import selectors
import socket


class StaticHttpServer(object):

    def __init__(self, host, port):
        self.selector = selectors.DefaultSelector()
        self.tcp_server_socket = socket.socket()
        self.tcp_server_socket.bind((host, port))
        self.tcp_server_socket.listen(5)
        self.tcp_server_socket.setblocking(False)

    def my_accept(self, sock, mask):
        conn, add = sock.accept()
        conn.setblocking(False)
        self.selector.register(conn, selectors.EVENT_READ, self.read)

    def read(self, conn, mask):
        data = conn.recv(1024)
        conn.setblocking(False)
        self.selector.unregister(conn)
        print(data)
        self.selector.register(conn, selectors.EVENT_WRITE, self.write)

    def write(self, conn, mask):
        retData = '''HTTP/1.1 200 OK\r\nServer:my_server\r\n\r\nHello World'''
        self.selector.unregister(conn)
        conn.send(retData.encode())
        conn.setblocking(False)

    def server_forever(self):
        self.selector.register(self.tcp_server_socket, selectors.EVENT_READ, self.my_accept)
        while True:
            events = self.selector.select()
            for key, mask in events:
                callback = key.data
                callback(key.fileobj, mask)


if __name__ == '__main__':
    host = '127.0.0.1'
    port = 8888
    tcp_server = StaticHttpServer(host, port)
    tcp_server.server_forever()

加上报文解析:

import selectors
import socket
from http_parsed import BaseRequest


class StaticHttpServer(object):

    def __init__(self, host, port):
        self.selector = selectors.DefaultSelector()
        self.tcp_server_socket = socket.socket()
        self.tcp_server_socket.bind((host, port))
        self.tcp_server_socket.listen(5)
        self.tcp_server_socket.setblocking(False)

    def my_accept(self, sock, mask):
        conn, add = sock.accept()
        conn.setblocking(False)
        self.selector.register(conn, selectors.EVENT_READ, self.read)

    def read(self, conn: socket.socket, mask):
        data = conn.recv(1024)
        if data:
            conn.setblocking(False)
            self.selector.unregister(conn)
            self.req = BaseRequest(data)
            print("请求方法:", self.req.method)
            print("请求路径:", self.req.path)
            print("请求头:", self.req.headers)
            print("请求体:", self.req.body)
            self.selector.register(conn, selectors.EVENT_WRITE, self.write)
        else:
            print("客户端离线")
            conn.close()

    def write(self, conn, mask):
        retData = '''HTTP/1.1 200 OK\r\nServer:my_server\r\n\r\nHello World'''
        self.selector.unregister(conn)
        conn.send(retData.encode())
        conn.setblocking(False)

    def server_forever(self):
        self.selector.register(self.tcp_server_socket, selectors.EVENT_READ, self.my_accept)
        try:
            while True:
                events = self.selector.select()
                for key, mask in events:
                    callback = key.data
                    callback(key.fileobj, mask)
        except Exception as e:
            print(e)
        finally:
            self.tcp_server_socket.close()


if __name__ == '__main__':
    host = '127.0.0.1'
    port = 8888
    tcp_server = StaticHttpServer(host, port)
    tcp_server.server_forever()

http_parsed.py

class BaseRequest(object):

    def __init__(self, request):
        self.request = request.decode()
        self.parse_headers()
        self.parse_body()
        self.parse_method()
        self.parse_path()

    def parse_headers(self):
        sp = self.request.split('\r\n\r\n', 1)[0].split('\r\n')[1:]
        dic = {}
        for i in sp:
            k, v = i.split(': ', 1)
            dic[k] = v
        self.headers = dic

    def parse_body(self):
        self.body = "Nothing to show" or self.request.split("\r\n")[-1]

    def parse_path(self):
        self.path = self.request.split()[1]

    def parse_method(self):
        self.method = self.request.split()[0]