05-使用面向对象思想进行封装

目标

  • 能够使用面向对象思想,对Web服务器进行封装

1. 功能分析

1、使用面向对象思想进行封装

2、通过对象方法.start() 启动web服务器

image-20181022112239975

2. 实现思路

1、创建HttpServer类

2、创建HttpServer类的构造方法,并在构造方法中对tcp_server_socket 创建初始化

3、创建start() 方法,用来Web服务器启动

3. 代码实现

import socket


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

        # 解码客户端发来的请求报文,得到请求行
        request_text = request_data.decode()
        # 得到请求行,使用"\r\n"拆分得到
        request_list = request_text.split("\r\n")
        # 得到请求路径
        request_line_parts = request_list[0].split(" ")
        file_path = request_line_parts[1]

        if file_path == "/":
            file_path = "/index.html"

        # 3、拼接响应报文
        #   3.1 响应行
        response_line = "HTTP/1.1 200 OK\r\n"
        #   3.2 响应头
        response_header = "Server:PythonWS/1.1\r\n"
        response_header = "Content-Type: text/html;charset=utf-8\r\n"
        #   3.3 响应空行
        response_blank = "\r\n"
        #   3.4 响应主体
        # response_body = "HelloWorld!"
        path_info = "static"+file_path

        try:
            # 如果报错,则执行此代码
            with open(path_info, "rb") as file:
                response_body = file.read()

        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 = (response_line + response_header + response_blank).encode() + response_body
        # 4、发送请求报文
        new_client_socket.send(response_data)
        # 5、关闭连接
        new_client_socket.close()


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

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


if __name__ == '__main__':
    main()