【从零学习python 】87. 手动搭建HTTP服务器的Python实现及多线程并发处理

2024-02-29 20:32:26 浏览数 (1)

导入必要的模块
代码语言:javascript复制
import re
import socket
from multiprocessing import Process

我们导入了re模块用于正则表达式操作,socket模块用于网络通信,以及multiprocessing模块中的Process类用于创建子进程

定义WSGIServer类
代码语言:javascript复制
class WSGIServer():
    def __init__(self, server, port, root):
        self.server = server
        self.port = port
        self.root = root
        self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.server_socket.bind((self.server, self.port))
        self.server_socket.listen(128)

在类的初始化方法__init__中,我们传入了服务器地址server、端口号port和根目录root作为参数,然后创建了一个socket对象server_socket,并设置了一些属性。我们通过bind方法将服务器地址和端口号绑定到server_socket上,并调用listen方法监听连接请求。

处理客户端请求
代码语言:javascript复制
def handle_socket(self, socket):
    data = socket.recv(1024).decode('utf-8').splitlines()[0]
    file_name = re.match(r'[^/] (/[^ ]*)', data)[1]

    if file_name == '/':
        file_name = self.root   '/index.html'
    else:
        file_name = self.root   file_name

    try:
        file = open(file_name, 'rb')
    except IOError:
        response_header = 'HTTP/1.1 404 NOT FOUND rn'
        response_header  = 'rn'
        response_body = '========Sorry,file not found======='.encode('utf-8')
    else:
        response_header = 'HTTP/1.1 200 OK rn'
        response_header  = 'rn'
        response_body = file.read()

    finally:
        socket.send(response_header.encode('utf-8'))
        socket.send(response_body)

接下来定义了一个handle_socket方法,用于处理客户端发来的请求。首先,我们通过socket.recv方法接收请求数据,并对数据进行解码。然后,使用正则表达式从请求数据中提取出文件名。如果文件名为根目录’/',我们将其设置为根目录下的’index.html’文件,否则拼接上根目录路径。然后,尝试打开对应的文件,如果文件不存在,我们返回404状态码和错误提示信息;如果文件存在,我们返回200状态码和文件内容作为响应体。 最后,我们通过finally块使用socket.send方法将响应头和响应体发送给客户端。

持续监听连接请求
代码语言:javascript复制
def forever_run(self):
    while True:
        client_socket, client_addr = self.server_socket.accept()
        p = Process(target=self.handle_socket, args=(client_socket,))
        p.start()
        client_socket.close()

在WSGIServer类中,定义了一个forever_run方法,用于持续监听连接请求。在循环中,我们使用accept方法接受客户端的连接请求,并创建一个子进程Process去处理连接请求,以实现多线程并发处理。然后关闭客户端套接字。

主程序入口
代码语言:javascript复制
if __name__ == '__main__':
    ip = '0.0.0.0'
    port = 8899
    server = WSGIServer(ip, port, './pages')
    print('server is running at {}:{}'.format(ip, port))
    server.forever_run()

在主程序中,我们实例化了WSGIServer类,并传入服务器地址、端口号和根目录的参数。然后打印出服务器运行的信息,最后调用forever_run方法开始监听连接请求。

0 人点赞