HTTP服务器--HTTP

本文深入探讨了HTTP协议的工作原理,详细解释了浏览器如何通过GET和POST方式向服务器发起请求,以及服务器如何响应这些请求。文章还提供了代码示例,展示了如何模拟浏览器和服务器的行为,包括处理不同类型的资源请求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

浏览器访问服务器的过程

在这里插入图片描述

http知识点

网址的构成

URL的格式为:

  • 协议部分:http://
  • 域名部分:news.china.com.cn
  • 资源路径部分:/2018-06/12/content_52060465.htm
域名组成:
  • 域名的组成:其实就是------ip + 端口(域名只是为了方便记忆)
  • 地址的组成:域名 + 具体的地址

HTTP包括请求和响应两种方式:

其中常用的请求方式有两种:GET 、POST
  • GET
    在这里插入图片描述

  • POST
    在这里插入图片描述

响应格式为:

在这里插入图片描述

get与post的区别(了解)

  • get请求的参数在地址栏进行拼接
  • post请求的参数通过body体进行传送
  • get地址栏最大能传的数据最大 2014字符
  • 相对来说get因为参数在地址栏显示,所以对比post不安全

请求报文

在这里插入图片描述

  • HTTP请求报文可以分为GET请求和POST请求报文,要注意的是GET请求没有请求体,POST请求有请求体信息

响应报文格式在这里插入图片描述

  • HTTP协议响应报文分为4部分,每部分之间使用\r\n进行分割响应行响应头空行(\r\n)响应体

模拟浏览器的功能实现(代码)

import socket

if __name__ == '__main__':
    # 创建tcp客户端套接字
    tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 建立连接
    tcp_client_socket.connect(("tlias3.boxuegu.com", 80))
    # 请求行
    request_line = "GET / HTTP/1.1\r\n"
    # 请求头
    request_header = "Host: tlias3.boxuegu.com\r\nConnection:close\r\n"
    # 准备http请求报文数据
    request_content = request_line + request_header + "\r\n"
    # 发送http请求报文数据
    tcp_client_socket.send(request_content.encode("utf-8"))
    # 定义二进制响应数据的类型
    result = b""
    # 接收服务端http响应报文数据
    while True:
        # 提示: 服务端断开连接,recv会解阻塞,返回的数据长度0
        # 提示: 以后可以通过Content-Length判断服务端发送数据的长度
        recv_data = tcp_client_socket.recv(1024)
        if recv_data:
            # 表示接收到了数据
            result += recv_data

            # print(result)
        else:
            break

    # 显示原始的响应报文数据
    print(result)
    # 解码 : 把二进制数据转成字符串
    response_content = result.decode("utf-8")
    # 根据指定标识数据进行分割
    response_list = response_content.split("\r\n\r\n", 1)
    # response_content.split("\r\n\r\n", maxsplit=1)

    print(len(response_list))
    print(response_list[1])
    # 关闭套接字
    tcp_client_socket.close()

模拟服务器的功能实现(基础版本)

# 三个地址/login.html /index.html /regedit.html
# 根据不同的地址进行不同的数据返回
# 1.创建一个tcp服务器
# 2. 得到请求的路径
# 3. 根据不同的路径返回不同的数据
import re
import socket


def client_exec(client):
    """处理客户端请求"""
    # 得到请求的路径
    data = client.recv(1024).decode('utf-8')
    print(data)
    # GET /center.html HTTP/1.1
    # GET / HTTP/1.1
    # 得到请求的地址使用正则
    # 得到匹配的对象
    match = re.match('[^/]+(/[^ ]*) ', data)
    # 判断是否匹配了
    if match:
        # 匹配
        # 获取请求的地址
        # 获取到文件地址
        file_path = match.group(1)

        # 如果你是地址是/那么访问首页/index.html
        if file_path == "/":
            file_path = "/index.html"
    else:
        # 没有匹配
        # 游览器都是匹配的,但是访问都是浏览器
        # 如果不是直接断开,返回
        client.close()
        return

    # 根据不同的路径返回不同的数据
    print("请求的地址", file_path)
    # 根据不同的路径返回不同的网页数据
    if file_path == "/index.html":
        # 返回index界面
        # 返回一个index界面内容
        # 响应行
        response_line = "HTTP/1.1 200 OK\r\n"
        # 响应头
        response_head = ""
        # 响应体
        response_body = "index page is show!"

        # 响应格式
        response_data = response_line + response_head + "\r\n" + response_body

        # 响应发送
        client.send(response_data.encode("utf-8"))

    elif file_path == "/login.html":
        # 返回login界面
        # 响应行
        response_line = "HTTP/1.1 200 OK\r\n"
        # 响应头
        response_head = ""
        # 响应体
        # 展示前端的界面
        # 1.读取前端的代码
        # 2.返回前端的代码
        with open("./post7.html", 'r') as f:
            content = f.read()

        response_body = content

        # 响应格式
        response_data = response_line + response_head + "\r\n" + response_body

        # 响应发送
        client.send(response_data.encode("utf-8"))
    elif file_path == "/regedit.html":
        # 返回regedit界面
        # 响应行
        response_line = "HTTP/1.1 200 OK\r\n"
        # 响应头
        response_head = ""
        # 响应体
        response_body = "regedit page is show!"

        # 响应格式
        response_data = response_line + response_head + "\r\n" + response_body

        # 响应发送
        client.send(response_data.encode("utf-8"))
    elif file_path == "/imgs/1.jpg":
        # 返回图片的内容
        # 响应行
        response_line = "HTTP/1.1 200 OK\r\n"
        # 响应头
        response_head = ""
        # 响应体
        # 打开图片的内容
        with open("./imgs/1.jpg", 'rb') as f:
            content = f.read()
        # 图片响应体
        response_body = content

        # 组合数据
        response_first = (response_line + response_head + "\r\n").encode("utf-8")

        # 发送的数据
        response_data = response_first + response_body

        client.send(response_data)
    elif file_path == "/imgs/2.jpg":
        # 返回图片的内容
        # 响应行
        response_line = "HTTP/1.1 200 OK\r\n"
        # 响应头
        response_head = ""
        # 响应体
        # 打开图片的内容
        with open("./imgs/2.jpg", 'rb') as f:
            content = f.read()
        # 图片响应体
        response_body = content

        # 组合数据
        response_first = (response_line + response_head + "\r\n").encode("utf-8")

        # 发送的数据
        response_data = response_first + response_body

        client.send(response_data)



    else:
        # 说明地址不存在
        # 如果网页地址不存在,那么404的显示
        # 响应行
        response_line = "HTTP/1.1 404 NOT FOUND\r\n"
        # 响应头
        response_head = ""
        # 响应体
        response_body = "not page is show!"
        # 响应的格式
        response_data = response_line + response_head + "\r\n" + response_body

        # 发送响应
        client.send(response_data.encode("utf-8"))

    # 关闭
    client.close()


def main():
    """http服务器"""
    # 1. 创建一个tcp服务器
    # 初始化套接字服务器
    # 1.创建套接字
    tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 2.绑定端口与复用端口
    tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    tcp_server.bind(("", 8080))
    # 3.被动模式
    tcp_server.listen(128)
    # 4. 处理客户端的请求
    while True:
        client, address = tcp_server.accept()
        # 处理客户端的请求
        client_exec(client)

    # 5.关闭
    tcp_server.close()


if __name__ == '__main__':
    main()

根据资源的特殊性进行处理

# 根据资源的特性进行特殊的处理,比如图片,视频,gif,这些做完以后,我们的程序不管在什么 时候访问都是一样的显示 或者处理.css .js
# 先判断如果是html后缀,那么我们一个一个网页的处理
# 如果是其他的我就直接打开返回数据
import re
import socket


def client_exec(client):
    """处理客户端请求"""
    # 得到请求的路径
    data = client.recv(1024).decode('utf-8')
    print(data)
    # GET /center.html HTTP/1.1
    # GET / HTTP/1.1
    # 得到请求的地址使用正则
    # 得到匹配的对象
    match = re.match('[^/]+(/[^ ]*) ', data)
    # 判断是否匹配了
    if match:
        # 匹配
        # 获取请求的地址
        # 获取到文件地址
        file_path = match.group(1)

        # 如果你是地址是/那么访问首页/index.html
        if file_path == "/":
            file_path = "/index.html"
    else:
        # 没有匹配
        # 游览器都是匹配的,但是访问都是浏览器
        # 如果不是直接断开,返回
        client.close()
        return

    # 根据不同的路径返回不同的数据
    print("请求的地址", file_path)
    # 根据特殊进行处理
    # 如果是html这个单独来处理
    # 如果是其他统一处理
    if file_path.endswith(".html"):  # 这个是以什么结尾
        # 网页单独处理
        if file_path == "/index.html":
            # 返回index界面
            # 返回一个index界面内容
            # 响应行
            response_line = "HTTP/1.1 200 OK\r\n"
            # 响应头
            response_head = ""
            # 响应体
            response_body = "index page is show!"

            # 响应格式
            response_data = response_line + response_head + "\r\n" + response_body

            # 响应发送
            client.send(response_data.encode("utf-8"))

        elif file_path == "/login.html":
            # 返回login界面
            # 响应行
            response_line = "HTTP/1.1 200 OK\r\n"
            # 响应头
            response_head = ""
            # 响应体
            # 展示前端的界面
            # 1.读取前端的代码
            # 2.返回前端的代码
            with open("./post7.html", 'r') as f:
                content = f.read()

            response_body = content

            # 响应格式
            response_data = response_line + response_head + "\r\n" + response_body

            # 响应发送
            client.send(response_data.encode("utf-8"))
        elif file_path == "/regedit.html":
            # 返回regedit界面
            # 响应行
            response_line = "HTTP/1.1 200 OK\r\n"
            # 响应头
            response_head = ""
            # 响应体
            response_body = "regedit page is show!"

            # 响应格式
            response_data = response_line + response_head + "\r\n" + response_body

            # 响应发送
            client.send(response_data.encode("utf-8"))
        else:
            # 网页找不到
            # 响应行
            response_line = "HTTP/1.1 404 NOT FOUND\r\n"
            # 响应头
            response_head = ""
            # 响应体
            response_body = "not page is show!"
            # 响应的格式
            response_data = response_line + response_head + "\r\n" + response_body

            # 发送
            client.send(response_data.encode("utf-8"))
    else:
        try:
            # 统一处理
            # 返回图片的内容
            # 响应行
            response_line = "HTTP/1.1 200 OK\r\n"
            # 响应头
            response_head = ""
            # 响应体
            # 打开图片的内容
            with open(".%s" % file_path, 'rb') as f:
                content = f.read()
            # 图片响应体
            response_body = content

            # 组合数据
            response_first = (response_line + response_head + "\r\n").encode("utf-8")

            # 发送的数据
            response_data = response_first + response_body

            client.send(response_data)
        except Exception as e:
            # 异常
            # 发送一个404
            response_line = "HTTP/1.1 404 NOT FOUND\r\n"
            response_head = ""
            response_body = ""

            # 发送数据
            response_data = response_line + response_head + "\r\n" + response_body
            client.send(response_data.encode("utf-8"))

    # 关闭
    client.close()


def main():
    """http服务器"""
    # 1. 创建一个tcp服务器
    # 初始化套接字服务器
    # 1.创建套接字
    tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 2.绑定端口与复用端口
    tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    tcp_server.bind(("", 8080))
    # 3.被动模式
    tcp_server.listen(128)
    # 4. 处理客户端的请求
    while True:
        client, address = tcp_server.accept()
        # 处理客户端的请求
        client_exec(client)

    # 5.关闭
    tcp_server.close()


if __name__ == '__main__':
    main()

重复的部分进行抽取(根据不同的地址返回不同的响应体),并实现多任务

import re
import socket
import threading


def client_exec(client):
    """处理客户端请求"""
    # 得到请求的路径
    data = client.recv(1024).decode('utf-8')
    print(data)
    # GET /center.html HTTP/1.1
    # GET / HTTP/1.1
    # 得到请求的地址使用正则
    # 得到匹配的对象
    match = re.match('[^/]+(/[^ ]*) ', data)
    # 判断是否匹配了
    if match:
        # 匹配
        # 获取请求的地址
        # 获取到文件地址
        file_path = match.group(1)

        # 如果你是地址是/那么访问首页/index.html
        if file_path == "/":
            file_path = "/index.html"
    else:
        # 没有匹配
        # 游览器都是匹配的,但是访问都是浏览器
        # 如果不是直接断开,返回
        client.close()
        return

    # 根据不同的路径返回不同的数据
    # 其实就核心就是返回不同的响应体
    print("请求的地址", file_path)
    # 根据特殊进行处理
    # 如果是html这个单独来处理
    # 如果是其他统一处理
    if file_path.endswith(".html"):  # 这个是以什么结尾
        # 响应行
        response_line = "HTTP/1.1 200 OK\r\n"
        # 响应头
        response_head = "content-type:text/html;charset=utf-8\r\n"

        # 网页单独处理
        if file_path == "/index.html":
            # 返回index界面
            # 返回一个index界面内容

            # 响应体
            response_body = "index page is show!我爱中国"

        elif file_path == "/login.html":
            # 返回login界面

            # 展示前端的界面
            # 1.读取前端的代码
            # 2.返回前端的代码
            with open("./post7.html", 'r') as f:
                content = f.read()

            response_body = content

        elif file_path == "/regedit.html":
            # 返回regedit界面

            # 响应体
            response_body = "regedit page is show!我爱中国"

        else:
            # 网页找不到
            # 响应行
            response_line = "HTTP/1.1 404 NOT FOUND\r\n"

            # 响应体
            response_body = "not page is show!"

        # 响应的格式
        response_data = response_line + response_head + "\r\n" + response_body

        # 发送
        client.send(response_data.encode("utf-8"))
    else:
        try:
            # 统一处理
            # 返回图片的内容
            # 响应行
            response_line = "HTTP/1.1 200 OK\r\n"
            # 响应头
            response_head = ""
            # 响应体
            # 打开图片的内容
            with open(".%s" % file_path, 'rb') as f:
                content = f.read()
            # 图片响应体
            response_body = content

            # 组合数据
            response_first = (response_line + response_head + "\r\n").encode("utf-8")

            # 发送的数据
            response_data = response_first + response_body

            client.send(response_data)
        except Exception as e:
            # 异常
            # 发送一个404
            response_line = "HTTP/1.1 404 NOT FOUND\r\n"
            response_head = ""
            response_body = ""

            # 发送数据
            response_data = response_line + response_head + "\r\n" + response_body
            client.send(response_data.encode("utf-8"))

    # 关闭
    client.close()


def main():
    """http服务器"""
    # 1. 创建一个tcp服务器
    # 初始化套接字服务器
    # 1.创建套接字
    tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 2.绑定端口与复用端口
    tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    tcp_server.bind(("", 8080))
    # 3.被动模式
    tcp_server.listen(128)
    # 4. 处理客户端的请求
    while True:
        client, address = tcp_server.accept()
        # 处理客户端的请求
        # 客户端处理的时候有可以会比较耗时我们放在多任务中
        threading.Thread(target=client_exec, args=(client,)).start()
    # client_exec(client)

    # 5.关闭
    tcp_server.close()


if __name__ == '__main__':
    main()

把逻辑抽取到一个单独的模块中

  • 目的是为了以后更换服务器,省去以后的麻烦
import re
import socket
import threading

import mini_web_12


def client_exec(client):
    """处理客户端请求"""
    # 得到请求的路径
    data = client.recv(1024).decode('utf-8')
    print(data)
    # GET /center.html HTTP/1.1
    # GET / HTTP/1.1
    # 得到请求的地址使用正则
    # 得到匹配的对象
    match = re.match('[^/]+(/[^ ]*) ', data)
    # 判断是否匹配了
    if match:
        # 匹配
        # 获取请求的地址
        # 获取到文件地址
        file_path = match.group(1)

        # 如果你是地址是/那么访问首页/index.html
        if file_path == "/":
            file_path = "/index.html"
    else:
        # 没有匹配
        # 游览器都是匹配的,但是访问都是浏览器
        # 如果不是直接断开,返回
        client.close()
        return

    # 根据不同的路径返回不同的数据
    # 其实就核心就是返回不同的响应体
    print("请求的地址", file_path)
    # 根据特殊进行处理
    # 如果是html这个单独来处理
    # 如果是其他统一处理
    if file_path.endswith(".html"):  # 这个是以什么结尾

        # 响应头
        # response_head = "content-type:text/html;charset=utf-8\r\n"

        # 得到一个模块
        response_line, response_head, response_body = mini_web_12.application(file_path)

        # 响应的格式
        response_data = response_line + response_head + "\r\n" + response_body

        # 发送
        client.send(response_data.encode("utf-8"))
    else:
        try:
            # 统一处理
            # 返回图片的内容
            # 响应行
            response_line = "HTTP/1.1 200 OK\r\n"
            # 响应头
            response_head = ""
            # 响应体
            # 打开图片的内容
            with open(".%s" % file_path, 'rb') as f:
                content = f.read()
            # 图片响应体
            response_body = content

            # 组合数据
            response_first = (response_line + response_head + "\r\n").encode("utf-8")

            # 发送的数据
            response_data = response_first + response_body

            client.send(response_data)
        except Exception as e:
            # 异常
            # 发送一个404
            response_line = "HTTP/1.1 404 NOT FOUND\r\n"
            response_head = ""
            response_body = ""

            # 发送数据
            response_data = response_line + response_head + "\r\n" + response_body
            client.send(response_data.encode("utf-8"))

    # 关闭
    client.close()


def main():
    """http服务器"""
    # 1. 创建一个tcp服务器
    # 初始化套接字服务器
    # 1.创建套接字
    tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    # 2.绑定端口与复用端口
    tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    tcp_server.bind(("", 8080))
    # 3.被动模式
    tcp_server.listen(128)
    # 4. 处理客户端的请求
    while True:
        client, address = tcp_server.accept()
        # 处理客户端的请求
        # 客户端处理的时候有可以会比较耗时我们放在多任务中
        threading.Thread(target=client_exec, args=(client,)).start()
    # client_exec(client)

    # 5.关闭
    tcp_server.close()


if __name__ == '__main__':
    main()
  • 抽取的模块为:mini_web12.py
# 根据不同的地址返回不同的响应体
def application(file_path):
    # 响应行
    response_line = "HTTP/1.1 200 OK\r\n"
    # 响应头
    response_head = "content-type:text/html;charset=utf-8\r\n"

    # 网页单独处理
    if file_path == "/index.html":
        # 返回index界面
        # 返回一个index界面内容

        # 响应体
        response_body = "index page is show!我爱中国"

    elif file_path == "/login.html":
        # 返回login界面

        # 展示前端的界面
        # 1.读取前端的代码
        # 2.返回前端的代码
        with open("./post7.html", 'r') as f:
            content = f.read()

        response_body = content

    elif file_path == "/regedit.html":
        # 返回regedit界面

        # 响应体
        response_body = "regedit page is show!我爱中国"

    else:
        # 网页找不到
        # 响应行
        response_line = "HTTP/1.1 404 NOT FOUND\r\n"

        # 响应体
        response_body = "not page is show!"

    return response_line, response_head, response_body

面向函数版

import re
import socket
import threading

import mini_web_14


def client_exec(client):
    """处理客户端请求"""
    # 得到请求的路径
    data = client.recv(1024).decode('utf-8')
    print(data)
    # GET /center.html HTTP/1.1
    # GET / HTTP/1.1
    # 得到请求的地址使用正则
    # 得到匹配的对象
    match = re.match('[^/]+(/[^ ]*) ', data)
    # 判断是否匹配了
    if match:
        # 匹配
        # 获取请求的地址
        # 获取到文件地址
        file_path = match.group(1)

        # 如果你是地址是/那么访问首页/index.html
        if file_path == "/":
            file_path = "/index.html"
    else:
        # 没有匹配
        # 游览器都是匹配的,但是访问都是浏览器
        # 如果不是直接断开,返回
        client.close()
        return

    # 根据不同的路径返回不同的数据
    # 其实就核心就是返回不同的响应体
    print("请求的地址", file_path)
    # 根据特殊进行处理
    # 如果是html这个单独来处理
    # 如果是其他统一处理
    if file_path.endswith(".html"):  # 这个是以什么结尾

        # 响应头
        # response_head = "content-type:text/html;charset=utf-8\r\n"

        # 得到一个模块
        response_line, response_head, response_body = mini_web_14.application(file_path)

        # 响应的格式
        response_data = response_line + response_head + "\r\n" + response_body

        # 发送
        client.send(response_data.encode("utf-8"))
    else:
        try:
            # 统一处理
            # 返回图片的内容
            # 响应行
            response_line = "HTTP/1.1 200 OK\r\n"
            # 响应头
            response_head = ""
            # 响应体
            # 打开图片的内容
            with open(".%s" % file_path, 'rb') as f:
                content = f.read()
            # 图片响应体
            response_body = content

            # 组合数据
            response_first = (response_line + response_head + "\r\n").encode("utf-8")

            # 发送的数据
            response_data = response_first + response_body

            client.send(response_data)
        except Exception as e:
            # 异常
            # 发送一个404
            response_line = "HTTP/1.1 404 NOT FOUND\r\n"
            response_head = ""
            response_body = ""

            # 发送数据
            response_data = response_line + response_head + "\r\n" + response_body
            client.send(response_data.encode("utf-8"))

    # 关闭
    client.close()


# 入口函数简洁
# 像目录一样
def main():
    """http服务器"""
    # 1. 创建一个tcp服务器
    tcp_server = init_tcp()
    # 2. 启动服务
    run_server(tcp_server)


def run_server(tcp_server):
    # 4. 处理客户端的请求
    while True:
        client, address = tcp_server.accept()
        # 处理客户端的请求
        # 客户端处理的时候有可以会比较耗时我们放在多任务中
        threading.Thread(target=client_exec, args=(client,)).start()
    # client_exec(client)
    # 5.关闭
    tcp_server.close()


def init_tcp():
    # 初始化套接字服务器
    # 1.创建套接字
    tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    # 2.绑定端口与复用端口
    tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    tcp_server.bind(("", 8080))
    # 3.被动模式
    tcp_server.listen(128)
    return tcp_server


if __name__ == '__main__':
    main()

口诀:一个函数一个功能, 类是相关函数的集合

面向对象版非完美版

  • ctrl + J 选出代码中相同的内容
  • Alt + 7 显示出代码中所有的函数
    在这里插入图片描述

面向对象完美版

  • self 就相当于一个菜篮子,这个方法内放,另一个方法内取,这样就不需要外部传参了。
import re
import socket
import threading

import mini_web_15


# 一个函数一个功能
# 类是相关函数的集合

class WebServer(object):
    def client_exec(self, client):
        """处理客户端请求"""
        # 得到请求的路径
        data = client.recv(1024).decode('utf-8')
        print(data)
        # GET /center.html HTTP/1.1
        # GET / HTTP/1.1
        # 得到请求的地址使用正则
        # 得到匹配的对象
        match = re.match('[^/]+(/[^ ]*) ', data)
        # 判断是否匹配了
        if match:
            # 匹配
            # 获取请求的地址
            # 获取到文件地址
            file_path = match.group(1)

            # 如果你是地址是/那么访问首页/index.html
            if file_path == "/":
                file_path = "/index.html"
        else:
            # 没有匹配
            # 游览器都是匹配的,但是访问都是浏览器
            # 如果不是直接断开,返回
            client.close()
            return

        # 根据不同的路径返回不同的数据
        # 其实就核心就是返回不同的响应体
        print("请求的地址", file_path)
        # 根据特殊进行处理
        # 如果是html这个单独来处理
        # 如果是其他统一处理
        if file_path.endswith(".html"):  # 这个是以什么结尾

            # 响应头
            # response_head = "content-type:text/html;charset=utf-8\r\n"

            # 得到一个模块
            response_line, response_head, response_body = mini_web_15.application(file_path)

            # 响应的格式
            response_data = response_line + response_head + "\r\n" + response_body

            # 发送
            client.send(response_data.encode("utf-8"))
        else:
            try:
                # 统一处理
                # 返回图片的内容
                # 响应行
                response_line = "HTTP/1.1 200 OK\r\n"
                # 响应头
                response_head = ""
                # 响应体
                # 打开图片的内容
                with open(".%s" % file_path, 'rb') as f:
                    content = f.read()
                # 图片响应体
                response_body = content

                # 组合数据
                response_first = (response_line + response_head + "\r\n").encode("utf-8")

                # 发送的数据
                response_data = response_first + response_body

                client.send(response_data)
            except Exception as e:
                # 异常
                # 发送一个404
                response_line = "HTTP/1.1 404 NOT FOUND\r\n"
                response_head = ""
                response_body = ""

                # 发送数据
                response_data = response_line + response_head + "\r\n" + response_body
                client.send(response_data.encode("utf-8"))

        # 关闭
        client.close()

    def run_server(self):
        # 4. 处理客户端的请求
        while True:
            client, address = self.tcp_server.accept()
            # 处理客户端的请求
            # 客户端处理的时候有可以会比较耗时我们放在多任务中
            threading.Thread(target=self.client_exec, args=(client,)).start()
        # client_exec(client)
        # 5.关闭
        tcp_server.close()

    def __init__(self):
        # 初始化套接字服务器
        # 1.创建套接字
        self.tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 2.绑定端口与复用端口
        self.tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        self.tcp_server.bind(("", 8080))
        # 3.被动模式
        self.tcp_server.listen(128)


# 入口函数简洁
# 像目录一样
def main():
    """http服务器"""
    # 1.初始化服务器
    # 初始化webserver
    server = WebServer()

    # 2.开启服务
    server.run_server()


if __name__ == '__main__':
    main()

mimi_web框架

口诀:

  • 入口函数要简洁,一个函数一个功能(即:一个 if 逻辑封装一个函数)
  • 如果 if 超过三个,可以考虑使用字典
  • 可是使用装饰器传参(自动生成一个字典)

逻辑抽取,原始mini_web

def application(file_path):
    # 响应行
    response_line = "HTTP/1.1 200 OK\r\n"
    # 响应头
    response_head = "content-type:text/html;charset=utf-8\r\n"

    # 网页单独处理
    if file_path == "/index.html":
        # 返回index界面
        # 返回一个index界面内容

        # 响应体
        response_body = "index page is show!我爱中国"

    elif file_path == "/login.html":
        # 返回login界面,yige rugu

        # 展示前端的界面
        # 1.读取前端的代码
        # 2.返回前端的代码
        with open("./post7.html", 'r') as f:
            content = f.read()

        response_body = content

    elif file_path == "/regedit.html":
        # 返回regedit界面

        # 响应体
        response_body = "regedit page is show!我爱中国"

    else:
        # 网页找不到
        # 响应行
        response_line = "HTTP/1.1 404 NOT FOUND\r\n"

        # 响应体
        response_body = "not page is show!"

    return response_line, response_head, response_body

第一步:

  • 入口函数要简洁,一个函数一个功能(即:一个 if 逻辑封装一个函数)
# 入口函数要简洁
# 一个函数一个功能
def application(file_path):
    # 响应行
    response_line = "HTTP/1.1 200 OK\r\n"
    # 响应头
    response_head = "content-type:text/html;charset=utf-8\r\n"

    # 网页单独处理
    if file_path == "/index.html":
        # 返回index界面
        # 返回一个index界面内容
        response_body = index()

    elif file_path == "/login.html":
        # 返回login界面
        response_body = login()

    elif file_path == "/regedit.html":
        # 返回regedit界面
        response_body = regedit()

    elif file_path == "/center.html":
        response_body = center()

    else:
        # 网页找不到
        # 响应行
        response_line = "HTTP/1.1 404 NOT FOUND\r\n"
        # 响应体
        response_body = "not page is show!"
        
    return response_line, response_head, response_body


def regedit():
    """注册"""
    # 响应体
    response_body = "regedit page is show!我爱中国"
    return response_body

def login():
    """登陆"""
    response_body = "login page is show!我爱中国"
    return response_body

def index():
    """首页"""
    # 响应体
    response_body = "index page is show!我爱中国"     
    return response_body

def center():
    """首页"""
    # 响应体
    response_body = "center page is show!我爱中国"
    return response_body

第二步:

  • 如果 if 超过三个,可以考虑使用字典
def application(file_path):
    # 响应行
    response_line = "HTTP/1.1 200 OK\r\n"
    # 响应头
    response_head = "content-type:text/html;charset=utf-8\r\n"
    
    try:
        # 创建一个字典,地址 与函数的引用
        url_dict = {"/index.html": index, "/login.html": login, "/regedit.html": regedit, "/center.html": center}

        # 根据不同的地址返回不同的响应体
        method = url_dict[file_path]  # 得到相应的函数

        response_body = method()  # 函数执行了
    except Exception as e:
        print("异常")
        # 网页找不到
        # 响应行
        response_line = "HTTP/1.1 404 NOT FOUND\r\n"
        # 响应体
        response_body = "not page is show!"

    return response_line, response_head, response_body

#########################################################

def regedit():
    """注册"""
    # 响应体
    response_body = "regedit page is show!我爱中国"
    return response_body

def login():
    """登陆"""
    response_body = "login page is show"
    return response_body

def index():
    """首页"""
    response_body = "index page is show"
    return response_body

def center():
    response_body = "center page is show"
    return response_body

第三部:

  • 使用装饰器传参,自动生成字典
# 入口函数要简洁
# 一个函数一个功能
# 如果if超过三个以上可以考虑使用字典

# 创建一个空的字典
url_dict = dict()


def route(url):
	def set_fun(func):
		def call_fun(*args, **kwargs):
			print("添加权限")
			return func(*args, **kwargs)

		print("装饰后的地址:", call_fun)
		print("装饰后的请求地址:", url)
		# 装饰后自动添加到对应的字典中
		url_dict[url] = call_fun

		return call_fun

	return set_fun


def application(file_path):
	# 响应行
	response_line = "HTTP/1.1 200 OK\r\n"
	# 响应头
	response_head = "content-type:text/html;charset=utf-8\r\n"
	try:		
		# 根据不同的地址返回不同的响应体
		method = url_dict[file_path]  # 得到相应的函数
		response_body = method()  # 函数执行了
		
	except Exception as e:
		print("异常")
		# 网页找不到
		# 响应行
		response_line = "HTTP/1.1 404 NOT FOUND\r\n"
		# 响应体
		response_body = "not page is show!"

	return response_line, response_head, response_body

############################上面是框架##################################
# 路由的作用是用来上网的
# 上网最早就是打开网页
# 一个页面一个功能
@route("/index.html")  # 路由的功能:控制你是否可以浏览这个网页
def index():
	return "index page is show"

@route("/center.html")
def center():
	return "center page is show"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值