06-服务端基础框架构建-2

目标

  • 能够优化代码,分模块开发

1. 整体功能:

1、创建框架构建相关的文件夹

2、创建 app模块文件

3、在app模块文件中创建 application函数(用于处理请求)

4、将request_handler()中的处理逻辑交由 app模块的 application函数完成

5、app模块的 application函数 响应数据

6、创建 utils 模块,并且在该模块中创建 create_http_response() 函数,专门用来拼接响应报文

7、在app模块的 application函数 中调用 utils 模块中的 create_http_response() 函,得到完整的响应报文

  • 逻辑关系

image-20181024235713839

  • 文件目录

image-20181025000037973

2. 实现效果

运行结果:

image-20180711223037272

3. 代码实现

  • 07-Web服务器_简单框架2.py 文件源代码

注意代码导入使用的是 from application import app

import socket
from application import app


class WebServer(object):
    """WebServer-Web服务器类"""

    # 定义初始化方法
    def __init__(self):
        # 1、创建套接字
        tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 2、设置套接字属性(地址可以重用)
        tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        # 3、绑定端口(8080)
        tcp_server_socket.bind(("", 8080))
        # 4、开启监听,设置套接字由主动设置为被动
        tcp_server_socket.listen(128)

        self.tcp_server_socket = tcp_server_socket

    # 定义启动服务器方法
    def start(self):

        while True:
            # 5、接受客户端连接并拆包
            new_client_socket, ip_port = self.tcp_server_socket.accept()
            # 6、调用 request_handler() 处理请求
            self.request_handler(new_client_socket, ip_port)

    # 定义响应服务器方法
    def request_handler(self, new_client_socket, ip_port):
        """接受客户端请求并处理"""
        # 1、接受客户端请求报文
        request_data = new_client_socket.recv(1024)
        # 2、判断客户端是否已经下线
        if not request_data:
            print("客户端[%s]已经下线~" % str(ip_port))
            new_client_socket.close()
            return

        # 调用 app 模块的 application 方法处理请求
        response_data = app.application(request_data)

        # 4、发送请求报文
        new_client_socket.send(response_data)
        # 5、关闭连接
        new_client_socket.close()


def main():
    """主入口方法"""
    # 1、创建对象
    ws = WebServer()

    # 2、启动服务器
    ws.start()


if __name__ == '__main__':
    main()
  • app模块代码

注意导入模块,使用的是:from application import utils

from application import utils


def parse_request(request_data):
    """处理客户端请求"""
    # 解码客户端发来的请求报文,得到请求行
    request_text = request_data.decode()
    # 得到请求行,使用"\r\n"拆分得到
    request_list = request_text.split("\r\n")
    # 得到请求路径
    request_line_parts = request_list[0].split(" ")
    # 定义空字典
    request_line_dict = dict()
    # 把资源路径保存到字典中
    #   key              value
    #  file_path ----> /index.html
    request_line_dict['file_path'] = request_line_parts[1]
    # 保存请求协议版本
    request_line_dict['version'] = request_line_parts[2]
    # 保存请求方式
    request_line_dict['method'] = request_line_parts[0]

    # 设置默认首页
    if request_line_dict['file_path'] == "/":
        request_line_dict['file_path'] = "/index.html"

    return request_line_dict


def application(current_dir, request_data):

    # 解析用户请求报文,得到请求信息的字典
    request_line_dict = parse_request(request_data)
    path_info = current_dir + request_line_dict['file_path']

    try:
        # 如果报错,则执行此代码
        with open(path_info, "rb") as file:
            response_body = file.read()
            # 调用方法,得到响应报文
            response_data = utils.create_http_response("200 OK", response_body)
    except Exception as e:
        # 重新设置请求行
        response_line = "HTTP/1.1 404 Not Found\r\n"
        # 重新设置响应信息为 错误信息
        response_body = "Error !! %s" % str(e)
        response_body = response_body.encode()
        response_data = utils.create_http_response("404 Not Found", response_body)

    return response_data
  • utils.py模块的 create_http_response()函数代码
def create_http_response(status, response_body):
    """
    :param status: 状态码
    :param response_body:响应主体
    :return:二进制响应报文
    """
    # 1、响应行
    response_line = "HTTP/1.1 %s OK\r\n" % status
    # 2、响应头
    response_header = "Server:Python20-WS/1.1\r\n"
    response_header += "Content-Type: text/html;charset=utf-8\r\n"
    # 3、响应空行
    response_blank = "\r\n"
    # 4、拼接响应报文
    response_data = (response_line + response_header + response_blank).encode() + response_body

    return response_data