美文网首页笔记本📒
Python静态Web服务器-返回指定页面数据

Python静态Web服务器-返回指定页面数据

作者: 涓涓自然卷 | 来源:发表于2021-01-22 09:51 被阅读0次

    \color{#FF69B4}{一、知识要点}

    1、获取用户请求资源的路径:
    request_list = client_request_data.split(" ")
    request_path = request_data[1]
    2、根据请求资源的路径,读取指定文件的数据:
    with open("./static" + request_path, "rb") as f:
    file_data = f.read()

    3、组装指定文件数据的响应报文,发送给浏览器:
    response_data = (response_line + response_header + "\r\n" + response_body).encode()
    client_socket.send(response_data)

    4、判断请求的文件在服务端不存在,组装404状态的响应报文,发给浏览器:
    try:
    # 打开指定文件,代码省略...
    except Exception as e:
    # 返回404错误数据
    client_socket.send(404响应报文数据)

    最简单的代码🌰:

    import socket
    
    # 获取用户请求资源的路径
    # 根据请求资源的路径,读取指定文件的数据
    # 组装指定文件数据的响应报文,发送给浏览器
    # 判断请求的文件在服务端不存在,组装404状态的响应报文,发给浏览器
    
    if __name__ == '__main__':
        # 1.编写一个TCP服务端程序
        # 创建socket
        tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        # 绑定地址
        tcp_server_socket.bind(("", 8080))
        # 设置监听
        tcp_server_socket.listen(128)
    
        # 循环客户端的连接请求
        while True:
            # 2.获取浏览器发送的HTTP请求报文数据
            # 建立链接
            client_socket, client_addr = tcp_server_socket.accept()
            # 获取浏览器的请求信息
            client_request_data = client_socket.recv(1024).decode()
            print(client_request_data)
            # 获取用户请求资源的路径
            request_data = client_request_data.split(" ")
            print(request_data)
            # 请求资源的路径
            request_path = request_data[1]
    
            if request_path == "/":
                request_path = "/index.html"
    
            # 3.读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器
            # 根据请求资源的路径,读取指定文件的数据
            try:
                with open("./static" + request_path, "rb") as f:
                    file_data = f.read()
            except Exception as e:
                # 返回404错误数据
                # 应答行
                response_line = "HTTP/1.1 404 Not Found\r\n"
                # 应答头
                response_header = "Server:pwb\r\n"
                # 应答体
                response_body = "404 Not Found sorry!"
                # 应答数据
                # 组装指定文件数据的响应报文,发送给浏览器
                response_data = (response_line + response_header + "\r\n" + response_body).encode()
    
                client_socket.send(response_data)
            else:
                # 应答行
                response_line = "HTTP/1.1 200 OK\r\n"
                # 应答头
                response_header = "Server:pwb\r\n"
                # 应答体
                response_body = file_data
                # 应答数据
                # 组装指定文件数据的响应报文,发送给浏览器
                response_data = (response_line + response_header + "\r\n").encode() + response_body
    
                client_socket.send(response_data)
            finally:
                # 4.HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字
                client_socket.close()
    
    

    运行效果

    1、浏览器访问根路径效果:


    访问根路径.png
    image.png

    2、浏览器访问index.html效果:


    index页面.png
    image.png

    3、浏览器访问index2.html效果:


    index2.png
    image.png

    4、浏览器访问错误路径效果:


    错误路径.png
    image.png

    备注:

    需要在当前目录下准备好js文件:


    image.png

    \color{#FF69B4}{二、多任务版知识要点}

    1、当客户端和服务端建立连接成功,创建子线程,使用子线程专门处理客户端的请求,防止主线程阻塞。
    关键代码:

    while True:
            client_socket, client_addr = tcp_server_socket.accept()
            # 开辟子线程并执行相应的任务
            sub_thread = threading.Thread(target=handel_client_request, args=(client_socket,))
            sub_thread.start()
    

    具体🌰:

    import socket
    import threading
    
    
    # 获取用户请求资源的路径
    # 根据请求资源的路径,读取指定文件的数据
    # 组装指定文件数据的响应报文,发送给浏览器
    # 判断请求的文件在服务端不存在,组装404状态的响应报文,发给浏览器
    
    
    def handel_client_request(client_socket):
        # 获取浏览器的请求信息
        client_request_data = \
            client_socket.recv(1024).decode()
        print(client_request_data)
        # 获取用户请求资源的路径
        request_data = client_request_data.split(" ")
        print(request_data)
    
        # 判断客户端是否关闭
        if len(request_data) == 1:
            client_socket.close()
            return
        # 请求资源的路径
        request_path = request_data[1]
    
        if request_path == "/":
            request_path = "/index.html"
    
        # 3.读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器
        # 根据请求资源的路径,读取指定文件的数据
        try:
            with open("./static" + request_path, "rb") as f:
                file_data = f.read()
        except Exception as e:
            # 返回404错误数据
            # 应答行
            response_line = "HTTP/1.1 404 Not Found\r\n"
            # 应答头
            response_header = "Server:pwb\r\n"
            # 应答体
            response_body = "404 Not Found sorry!"
            # 应答数据
            # 组装指定文件数据的响应报文,发送给浏览器
            response_data = (response_line + response_header + "\r\n" + response_body).encode()
    
            client_socket.send(response_data)
        else:
            # 应答行
            response_line = "HTTP/1.1 200 OK\r\n"
            # 应答头
            response_header = "Server:pwb\r\n"
            # 应答体
            response_body = file_data
            # 应答数据
            # 组装指定文件数据的响应报文,发送给浏览器
            response_data = (response_line + response_header + "\r\n").encode() + response_body
    
            client_socket.send(response_data)
        finally:
            # 4.HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字
            client_socket.close()
    
    
    if __name__ == '__main__':
        # 1.编写一个TCP服务端程序
        # 创建socket
        tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        # 绑定地址
        tcp_server_socket.bind(("", 8080))
        # 设置监听
        tcp_server_socket.listen(128)
    
        # 循环客户端的连接请求
        while True:
            # 2.获取浏览器发送的HTTP请求报文数据
            # 建立链接
            client_socket, client_addr = tcp_server_socket.accept()
            # 创建子线程
            sub_thread = threading.Thread(target=handel_client_request, args=(client_socket,))
            sub_thread.start()
    
    

    \color{#FF69B4}{三、面向对象版知识要点-基于之前代码进行代码优化}

    1、把提供服务的Web服务器抽象成一个类(HTTPWebServer)
    2、提供Web服务器的初始化方法,在初始化方法里面创建socket对象
    3、提供一个开启Web无服务的方法,让Web服务器处理客户端请求操作。

    具体代码🌰:

    import socket
    import threading
    
    
    # 获取用户请求资源的路径
    # 根据请求资源的路径,读取指定文件的数据
    # 组装指定文件数据的响应报文,发送给浏览器
    # 判断请求的文件在服务端不存在,组装404状态的响应报文,发给浏览器
    
    
    class HttpWebServer:
        def __init__(self):
            # 1.编写一个TCP服务端程序
            # 创建socket
            self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
            # 绑定地址
            self.tcp_server_socket.bind(("", 8080))
            # 设置监听
            self.tcp_server_socket.listen(128)
    
        def handel_client_request(self, client_socket):
            # 获取浏览器的请求信息
            client_request_data = \
                client_socket.recv(1024).decode()
            print(client_request_data)
            # 获取用户请求资源的路径
            request_data = client_request_data.split(" ")
            print(request_data)
    
            # 判断客户端是否关闭
            if len(request_data) == 1:
                client_socket.close()
                return
            # 请求资源的路径
            request_path = request_data[1]
    
            if request_path == "/":
                request_path = "/index.html"
    
            # 3.读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器
            # 根据请求资源的路径,读取指定文件的数据
            try:
                with open("./static" + request_path, "rb") as f:
                    file_data = f.read()
            except Exception as e:
                # 返回404错误数据
                # 应答行
                response_line = "HTTP/1.1 404 Not Found\r\n"
                # 应答头
                response_header = "Server:pwb\r\n"
                # 应答体
                response_body = "404 Not Found sorry!"
                # 应答数据
                # 组装指定文件数据的响应报文,发送给浏览器
                response_data = (response_line + response_header + "\r\n" + response_body).encode()
    
                client_socket.send(response_data)
            else:
                # 应答行
                response_line = "HTTP/1.1 200 OK\r\n"
                # 应答头
                response_header = "Server:pwb\r\n"
                # 应答体
                response_body = file_data
                # 应答数据
                # 组装指定文件数据的响应报文,发送给浏览器
                response_data = (response_line + response_header + "\r\n").encode() + response_body
    
                client_socket.send(response_data)
            finally:
                # 4.HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字
                client_socket.close()
    
        def start(self):
            # 循环客户端的连接请求
            while True:
                # 2.获取浏览器发送的HTTP请求报文数据
                # 建立链接
                client_socket, client_addr = self.tcp_server_socket.accept()
                # 创建子线程
                sub_thread = threading.Thread(target=self.handel_client_request, args=(client_socket,))
                sub_thread.start()
    
    
    if __name__ == '__main__':
        # 创建服务器对象
        my_web_server = HttpWebServer()
        # 启动服务器
        my_web_server.start()
    
    

    \color{#FF69B4}{四、命令行启动动态绑定端口号知识要点}

    1、获取执行python程序的撞断命令行参数
    sys.argv
    2、判断参数的类型,设置端口号必须是整型
    3、给Web服务器的初始化方法添加一个端口号参数,用于绑定端口号

    pycharm代码🌰:

    import socket
    import threading
    import sys
    
    
    # 获取用户请求资源的路径
    # 根据请求资源的路径,读取指定文件的数据
    # 组装指定文件数据的响应报文,发送给浏览器
    # 判断请求的文件在服务端不存在,组装404状态的响应报文,发给浏览器
    
    
    class HttpWebServer():
        def __init__(self, port):
            # 1.编写一个TCP服务端程序
            # 创建socket
            self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
            # 绑定地址
            self.tcp_server_socket.bind(("", port))
            # 设置监听
            self.tcp_server_socket.listen(128)
    
        def handel_client_request(self, client_socket):
            # 获取浏览器的请求信息
            client_request_data = \
                client_socket.recv(1024).decode()
            print(client_request_data)
            # 获取用户请求资源的路径
            request_data = client_request_data.split(" ")
            print(request_data)
    
            # 判断客户端是否关闭
            if len(request_data) == 1:
                client_socket.close()
                return
            # 请求资源的路径
            request_path = request_data[1]
    
            if request_path == "/":
                request_path = "/index.html"
    
            # 3.读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器
            # 根据请求资源的路径,读取指定文件的数据
            try:
                with open("./static" + request_path, "rb") as f:
                    file_data = f.read()
            except Exception as e:
                # 返回404错误数据
                # 应答行
                response_line = "HTTP/1.1 404 Not Found\r\n"
                # 应答头
                response_header = "Server:pwb\r\n"
                # 应答体
                response_body = "404 Not Found sorry!"
                # 应答数据
                # 组装指定文件数据的响应报文,发送给浏览器
                response_data = (response_line + response_header + "\r\n" + response_body).encode()
    
                client_socket.send(response_data)
            else:
                # 应答行
                response_line = "HTTP/1.1 200 OK\r\n"
                # 应答头
                response_header = "Server:pwb\r\n"
                # 应答体
                response_body = file_data
                # 应答数据
                # 组装指定文件数据的响应报文,发送给浏览器
                response_data = (response_line + response_header + "\r\n").encode() + response_body
    
                client_socket.send(response_data)
            finally:
                # 4.HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字
                client_socket.close()
    
        def start(self):
            # 循环客户端的连接请求
            while True:
                # 2.获取浏览器发送的HTTP请求报文数据
                # 建立链接
                client_socket, client_addr = self.tcp_server_socket.accept()
                # 创建子线程
                sub_thread = threading.Thread(target=self.handel_client_request, args=(client_socket,))
                sub_thread.start()
    
    
    def main():
        # 获取执行python程序的终端命令行参数
        print(sys.argv)
        if len(sys.argv) != 2:
            print("格式错误 python3 XXX.py 9090")
            return
        # 判断参数的类型,设置端口号必须是整型
        if not sys.argv[1].isdigit():
            print("格式错误 python3 XXX.py 9090")
            return
        port = int(sys.argv[1])
        # 创建服务器对象
        # 给Web服务器类的初始化方法添加一个端口号参数,用于绑定端口号
        my_web_server = HttpWebServer(port)
        # 启动服务器
        my_web_server.start()
    
    
    if __name__ == '__main__':
        main()
    
    

    终端命令行执行命令:

    ➜  hm-test01 python 05-静态Web服务器-命令行启动动态绑定端口号.py 8888
    ['05-静态Web服务器-命令行启动动态绑定端口号.py', '8888']
    

    相关文章

      网友评论

        本文标题:Python静态Web服务器-返回指定页面数据

        本文链接:https://www.haomeiwen.com/subject/yeqszktx.html