【Python使用】嘿马python高级进阶全体系教程第10篇:静态Web服务器-返回固定页面数据,1. 开发自己的静态Web服务器【附代码文档】

本教程的知识点为:操作系统 1. 常见的操作系统 4. 小结 ls命令选项 2. 小结 mkdir和rm命令选项 1. mkdir命令选项 压缩和解压缩命令 1. 压缩格式的介绍 2. tar命令及选项的使用 3. zip和unzip命令及选项的使用 4. 小结 编辑器 vim 1. vim 的介绍 2. vim 的工作模式 3. vim 的末行模式命令 4. vim 的常用命令 获取进程编号 1. 获取进程编号的目的 2. 获取当前进程编号 3. 获取当前父进程编号 4. 小结 线程执行带有参数的任务 1. 线程执行带有参数的任务的介绍 2. args参数的使用 3. kwargs参数的使用 4. 小结 1. s锁的概念 2. s锁示例 3. 避免s锁 4. 小结 端口和端口号的介绍 1. 问题思考 2. 什么是端口 3. 什么端口号 4. 端口和端口号的关系 HTTP 协议 1. HTTP 协议的介绍 2. HTTP 协议的作用 3. 浏览器访问web服务器的通信过程 4. 小结 静态Web服务器-返回固定页面数据 1. 开发自己的静态Web服务器 2. 静态Web服务器-返回固定页面数据的示例代码 3. 小结 静态Web服务器-返回指定页面数据 静态Web服务器-面向对象开发 1. 以面向对象的方式开发静态Web服务器 2. 静态Web服务器-面向对象开发的示例代码 3. 小结 静态Web服务器-命令行启动动态绑定端口号 修改闭包内使用的外部变量 1. 修改闭包内使用的外部变量 2. 小结 装饰器 1. 装饰器的定义 property属性 1. property属性的介绍 2. 装饰器方式 3. 类属性方式 4. 小结 深拷贝和浅拷贝 1. 浅拷贝 2. 深拷贝 3. 浅拷贝和深拷贝的区别 4. 总结 匹配多个字符 1. 匹配多个字符 示例1:* 示例2:+ 示例3:?

完整笔记资料代码:https://gitee.com/yinuo112/Backend/tree/master/Python/嘿马python高级进阶全体系教程/note.md

感兴趣的小伙伴可以自取哦~


全套教程部分目录:


部分文件图片:

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

学习目标

  • 能够写出组装固定页面数据的响应报文

1. 开发自己的静态Web服务器

实现步骤:

  1. 编写一个TCP服务端程序
  2. 获取浏览器发送的http请求报文数据
  3. 读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器。
  4. HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字。

2. 静态Web服务器-返回固定页面数据的示例代码

py 复制代码
import socket


if __name__ == '__main__':
    # 创建tcp服务端套接字
    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(("", 9000))
    # 设置监听
    tcp_server_socket.listen(128)
    while True:
        # 等待接受客户端的连接请求
        new_socket, ip_port = tcp_server_socket.accept()
        # 代码执行到此,说明连接建立成功
        recv_client_data = new_socket.recv(4096)
        # 对二进制数据进行解码
        recv_client_content = recv_client_data.decode("utf-8")
        print(recv_client_content)

        with open("static/index.html", "rb") as file:
            # 读取文件数据
            file_data = file.read()


        # 响应行
        response_line = "HTTP/1.1 200 OK\r\n"
        # 响应头
        response_header = "Server: PWS1.0\r\n"

        # 响应体
        response_body = file_data

        # 拼接响应报文
        response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
        # 发送数据
        new_socket.send(response_data)

        # 关闭服务与客户端的套接字
        new_socket.close()

3. 小结

  1. 编写一个TCP服务端程序
py 复制代码
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)


# 循环接受客户端的连接请求


while True:
    conn_socket, ip_port = tcp_server_socket.accept()
  1. 获取浏览器发送的http请求报文数据
py 复制代码
client_request_data = conn_socket.recv(4096)
  1. 读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器。
py 复制代码
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
conn_socket.send(response_data)
  1. HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字。
py 复制代码
conn_socket.close()

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

学习目标

  • 能够写出组装指定页面数据的响应报文

1. 静态Web服务器的问题

目前的Web服务器,不管用户访问什么页面,返回的都是固定页面的数据,接下来需要根据用户的请求返回指定页面的数据

返回指定页面数据的实现步骤:

  1. 获取用户请求资源的路径
  2. 根据请求资源的路径,读取指定文件的数据
  3. 组装指定文件数据的响应报文,发送给浏览器
  4. 判断请求的文件在服务端不存在,组装404状态的响应报文,发送给浏览器

2. 静态Web服务器-返回指定页面数据的示例代码

py 复制代码
import socket


def main():
    # 创建tcp服务端套接字
    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(("", 9000))
    # 设置监听
    tcp_server_socket.listen(128)
    while True:
        # 等待接受客户端的连接请求
        new_socket, ip_port = tcp_server_socket.accept()
        # 代码执行到此,说明连接建立成功
        recv_client_data = new_socket.recv(4096)
        if len(recv_client_data) == 0:
            print("关闭浏览器了")
            new_socket.close()
            return

        # 对二进制数据进行解码
        recv_client_content = recv_client_data.decode("utf-8")
        print(recv_client_content)
        # 根据指定字符串进行分割, 最大分割次数指定2
        request_list = recv_client_content.split(" ", maxsplit=2)

        # 获取请求资源路径
        request_path = request_list[1]
        print(request_path)

        # 判断请求的是否是根目录,如果条件成立,指定首页数据返回
        if request_path == "/":
            request_path = "/index.html"

        try:
            # 动态打开指定文件
            with open("static" + request_path, "rb") as file:
                # 读取文件数据
                file_data = file.read()
        except Exception as e:
            # 请求资源不存在,返回404数据
            # 响应行
            response_line = "HTTP/1.1 404 Not Found\r\n"
            # 响应头
            response_header = "Server: PWS1.0\r\n"
            with open("static/error.html", "rb") as file:
                file_data = file.read()
            # 响应体
            response_body = file_data

            # 拼接响应报文
            response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
            # 发送数据
            new_socket.send(response_data)
        else:
            # 响应行
            response_line = "HTTP/1.1 200 OK\r\n"
            # 响应头
            response_header = "Server: PWS1.0\r\n"

            # 响应体
            response_body = file_data

            # 拼接响应报文
            response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
            # 发送数据
            new_socket.send(response_data)
        finally:
            # 关闭服务与客户端的套接字
            new_socket.close()

if __name__ == '__main__':
    main()

3. 小结

  1. 获取用户请求资源的路径
py 复制代码
request_list = client_request_conent.split(" ",  maxsplit=2)
 request_path = request_list[1]
  1. 根据请求资源的路径,读取请求指定文件的数据
py 复制代码
with open("static" + request_path, "rb") as file:
 file_data = file.read()
  1. 组装指定文件数据的响应报文,发送给浏览器
py 复制代码
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
 conn_socket.send(response_data)
  1. 判断请求的文件在服务端不存在,组装404状态的响应报文,发送给浏览器
py 复制代码
try:
     # 打开指定文件,代码省略...
 except Exception as e:
     conn_socket.send(404响应报文数据)

静态Web服务器-多任务版

学习目标

  • 能够写出多线程版的多任务web服务器程序

1. 静态Web服务器的问题

目前的Web服务器,不能支持多用户同时访问,只能一个一个的处理客户端的请求,那么如何开发多任务版的web服务器同时处理 多个客户端的请求?

可以使用多线程,比进程更加节省内存资源。

多任务版web服务器程序的实现步骤:

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

  2. 把创建的子线程设置成为守护主线程,防止主线程无法退出。

2. 静态Web服务器-多任务版的示例代码

py 复制代码
import socket
import threading




# 处理客户端的请求


def handle_client_request(new_socket):
    # 代码执行到此,说明连接建立成功
    recv_client_data = new_socket.recv(4096)
    if len(recv_client_data) == 0:
        print("关闭浏览器了")
        new_socket.close()
        return

    # 对二进制数据进行解码
    recv_client_content = recv_client_data.decode("utf-8")
    print(recv_client_content)
    # 根据指定字符串进行分割, 最大分割次数指定2
    request_list = recv_client_content.split(" ", maxsplit=2)

    # 获取请求资源路径
    request_path = request_list[1]
    print(request_path)

    # 判断请求的是否是根目录,如果条件成立,指定首页数据返回
    if request_path == "/":
        request_path = "/index.html"

    try:
        # 动态打开指定文件
        with open("static" + request_path, "rb") as file:
            # 读取文件数据
            file_data = file.read()
    except Exception as e:
        # 请求资源不存在,返回404数据
        # 响应行
        response_line = "HTTP/1.1 404 Not Found\r\n"
        # 响应头
        response_header = "Server: PWS1.0\r\n"
        with open("static/error.html", "rb") as file:
            file_data = file.read()
        # 响应体
        response_body = file_data

        # 拼接响应报文
        response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
        # 发送数据
        new_socket.send(response_data)
    else:
        # 响应行
        response_line = "HTTP/1.1 200 OK\r\n"
        # 响应头
        response_header = "Server: PWS1.0\r\n"

        # 响应体
        response_body = file_data

        # 拼接响应报文
        response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
        # 发送数据
        new_socket.send(response_data)
    finally:
        # 关闭服务与客户端的套接字
        new_socket.close()




# 程序入口函数


def main():
    # 创建tcp服务端套接字
    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(("", 9000))
    # 设置监听
    tcp_server_socket.listen(128)

    while True:
        # 等待接受客户端的连接请求
        new_socket, ip_port = tcp_server_socket.accept()
        print(ip_port)
        # 当客户端和服务器建立连接程,创建子线程
        sub_thread = threading.Thread(target=handle_client_request, args=(new_socket,))
        # 设置守护主线程
        sub_thread.setDaemon(True)
        # 启动子线程执行对应的任务
        sub_thread.start()


if __name__ == '__main__':
    main()

3. 小结

  1. 当客户端和服务端建立连接成功,创建子线程,使用子线程专门处理客户端的请求,防止主线程阻塞。
py 复制代码
while True:
     conn_socket, ip_port = tcp_server_socket.accept()
     # 开辟子线程并执行对应的任务
     sub_thread = threading.Thread(target=handle_client_request, args=(conn_socket,))
  1. 把创建的子线程设置成为守护主线程,防止主线程无法退出。
py 复制代码
# 开辟子线程并执行对应的任务


 sub_thread = threading.Thread(target=handle_client_request, args=(conn_socket,))
 sub_thread.setDaemon(True) # 设置守护主线程
 sub_thread.start()
相关推荐
兵慌码乱10 小时前
基于 MediaPipe 与 PySide2 的手势交互音乐控制系统实现:轻量化视觉交互全流程解析
python·opencv·计算机视觉·人机交互·手势识别·mediapipe·pyside2
IT_陈寒11 小时前
Redis内存爆了,原来我漏掉了这个致命配置
前端·人工智能·后端
fliter12 小时前
最后一块拼图:用 bitvec 构造 IPv4 包,真正做出自己的 Ping
后端
luckdewei13 小时前
FastAPI 资产管理系统实战:复杂 ORM 关联、Alembic 迁移与 N+1 查询优化
python
fliter13 小时前
用 Rust 解析并生成 ICMP 包:checksum、nom 与 cookie-factory
后端
蝎子莱莱爱打怪13 小时前
XZLL-IM干货系列 03|消息 ID 设计:一个 UUID 搞不定的事,我用两个 ID 解决了
后端·面试·开源
fliter13 小时前
从 panic 到 Result:用 Rust 重新整理一个 ping 项目的错误处理
后端
森蓝情丶14 小时前
我给 AI 搭了个法庭:一个前端仔的 LangGraph 实战全记录
前端·后端
JensCS猿14 小时前
从 Spring Boot 回看 SSM 框架:手动挡与自动挡的驾驶哲学
后端
爱勇宝14 小时前
干了近 8 年,一夜之间被裁:AI 时代,程序员最该害怕的不是 AI
前端·后端·程序员