Python builds a simple server

Keywords: socket Python

Python dynamic server web page (WSGI interface is required). The basic implementation steps are as follows:
1. Wait for the client's link, and the server will receive an http protocol request datagram
2. Use regular expression to parse the request datagram (request mode, environment for extracting files)
3. After extracting the file environment, the file name is converted to the module name by truncating the fetching method
4. Use m = import () to get a module with a return value of m
5. Create an env Dictionary: it contains various key value pairs such as request mode and file environment
6. Create a new dynamic script, in which the application function is defined, and it must contain the parameters of env and start'u response (also the call method in the server)
7. Define status code and response headers in this dynamic script (note that they are in dictionary form, such as content type)
8. Then call start'u response (status, headers), but note that this function is defined on the server
9. Write dynamic execution program in dynamic script
The return value of 10. M.application is the body of the response packet. Its data header is integrated in start response
11. The dynamic web page can be displayed by splicing the data header with the data body and sending it to the client

MyWebServer
# coding:utf-8
import socket
import re
import sys

from multiprocessing import Process
from MyWebFramework import Application

#Set static file root
HTML_ROOT_DIR = "./html"
WSGI_PYTHON_DIR = "./wsgipython"

class HTTPServer(object):
    """"""
    def __init__(self, application):
        """Constructor, application Refers to the framework app"""
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.app = application

    def start(self):
        self.server_socket.listen(128)
        while True:
            client_socket, client_address = self.server_socket.accept()
            #print("[%s,%s] user connected"% (client [u address [0], client [u address [1]))
            print("[%s, %s]User connected" % client_address)
            handle_client_process = Process(target=self.handle_client, args=(client_socket,))
            handle_client_process.start()
            client_socket.close()

    def start_response(self, status, headers):
        """
         status = "200 OK"
    headers = [
        ("Content-Type", "text/plain")
    ]
    star 
        """
        response_headers = "HTTP/1.1 " + status + "\r\n"
        for header in headers:
            response_headers += "%s: %s\r\n" % header

        self.response_headers = response_headers

    def handle_client(self, client_socket):
        """Processing client requests"""
        #Get client request data
        request_data = client_socket.recv(1024)
        print("request data:", request_data)
        request_lines = request_data.splitlines()
        for line in request_lines:
            print(line)

        #Parse request message
        # 'GET / HTTP/1.1'
        request_start_line = request_lines[0]
        #Extract the file name requested by the user
        print("*" * 10)
        print(request_start_line.decode("utf-8"))
        file_name = re.match(r"\w+ +(/[^ ]*) ", request_start_line.decode("utf-8")).group(1)
        method = re.match(r"(\w+) +/[^ ]* ", request_start_line.decode("utf-8")).group(1)

        env = {
            "PATH_INFO": file_name,
            "METHOD": method
        }
        response_body = self.app(env, self.start_response)
        response = self.response_headers + "\r\n" + response_body

        #Return response data to client
        client_socket.send(bytes(response, "utf-8"))
        #Close client connection
        client_socket.close()

    def bind(self, port):
        self.server_socket.bind(("", port))

def main():
    sys.path.insert(1, WSGI_PYTHON_DIR)
    if len(sys.argv) < 2:
        sys.exit("python MyWebServer.py Module:app")
    # python MyWebServer.py  MyWebFrameWork:app
    module_name, app_name = sys.argv[1].split(":")
    # module_name = "MyWebFrameWork"
    # app_name = "app"
    m = __import__(module_name)
    app = getattr(m, app_name)
    http_server = HTTPServer(app)
    # http_server.set_port
    http_server.bind(8000)
    http_server.start()

if __name__ == "__main__":
    main()
MyWebFrameWork
# coding:utf-8
import time
# from MyWebServer import HTTPServer

#Set static file root
HTML_ROOT_DIR = "./html"

class Application(object):
    """The core part of the framework, that is, the subject program of the framework, and the framework is universal"""
    def __init__(self, urls):
        #Set routing information
        self.urls = urls

    def __call__(self, env, start_response):
        path = env.get("PATH_INFO", "/")
        # /static/index.html
        if path.startswith("/static"):
            #To access static files
            file_name = path[7:]
            #Open file, read content
            try:
                file = open(HTML_ROOT_DIR + file_name, "rb")
            except IOError:
                #No routing information found on behalf of, 404 error
                status = "404 Not Found"
                headers = []
                start_response(status, headers)
                return "not found"
            else:
                file_data = file.read()
                file.close()

                status = "200 OK"
                headers = []
                start_response(status, headers)
                return file_data.decode("utf-8")

        for url, handler in self.urls:
            #("/ctime", show_ctime)
            if path == url:
                return handler(env, start_response)

        #No routing information found on behalf of, 404 error
        status = "404 Not Found"
        headers = []
        start_response(status, headers)
        return "not found"

def show_ctime(env, start_response):
    status = "200 OK"
    headers = [
        ("Content-Type", "text/plain")
    ]
    start_response(status, headers)
    return time.ctime()

def say_hello(env, start_response):
    status = "200 OK"
    headers = [
        ("Content-Type", "text/plain")
    ]
    start_response(status, headers)
    return "hello itcast"

def say_haha(env, start_response):
    status = "200 OK"
    headers = [
        ("Content-Type", "text/plain")
    ]
    start_response(status, headers)
    return "hello haha"

urls = [
            ("/", show_ctime),
            ("/ctime", show_ctime),
            ("/sayhello", say_hello),
            ("/sayhaha", say_haha),
        ]
app = Application(urls)
# if __name__ == "__main__":
#     urls = [
#             ("/", show_ctime),
#             ("/ctime", show_ctime),
#             ("/sayhello", say_hello),
#             ("/sayhaha", say_haha),
#         ]
#     app = Application(urls)
#     http_server = HTTPServer(app)
#     http_server.bind(8000)
#     http_server.start()

Posted by nonlinear on Wed, 01 Jan 2020 06:52:42 -0800