综合-实践 WebServer

# 进阶\py\WebServer\WebServer_app.py
import WebServer_utils
def application(current_dir, request_data):
    # 根据客户端浏览器请求的资源路径,返回请求资源
    request_line_path = request_data.split("\r\n")[0].split(" ")[1]
    print(request_line_path)
    # 配置默认访问页面
    if request_line_path == "/":
        request_line_path = "/index.html"
    try:
        # 通过with open读取文件
        with open(f"{current_dir}{request_line_path}", "rb") as file:
            response_body = file.read()
        # 调用utils模块的create_http_response函数接接响应信息
        status = "200 OK"
        response_data = WebServer_utils.create_http_response(status, response_body)
    except Exception as e:
        print("访问路径不存在!请重试!")
        response_body = f"Error! 页面{request_line_path}不存在!"
        response_body = response_body.encode("GBK")
        status = "404 Not Found"
        response_data = WebServer_utils.create_http_response(status, response_body)

    return response_data

def application_game(current_dir, request_data):
    # 根据客户端浏览器请求的资源路径,返回请求资源
    request_line_path = request_data.split("\r\n")[0].split(" ")[1]
    print(current_dir+request_line_path)
    # 配置默认访问页面
    if request_line_path == "/":
        request_line_path = f"/index.html"
    try:
        # 通过with open读取文件
        with open(f"{current_dir}{request_line_path}", "rb") as file:
            response_body = file.read()
        # 调用utils模块的create_http_response函数接接响应信息
        status = "200 OK"
        response_data = WebServer_utils.create_http_response(status, response_body)
    except Exception as e:
        print("访问路径不存在!请重试!")
        response_body = f"Error! 页面{request_line_path}不存在!"
        response_body = response_body.encode("GBK")
        status = "404 Not Found"
        response_data = WebServer_utils.create_http_response(status, response_body)

    return response_data
# 进阶\py\WebServer\WebServer_cli.py
#!/usr/bin/python
"""
1、导入模块
2、创建套接字
3、设置地址重用
4、绑定端口
5、设置监听,让套接字由主动变为被动接收
6、接受客户端连接  定义函数 request_handler()
7、接收客户端浏览器发送的请求协议
8、判断协议是否为空
9、拼接响应的报文
10、发送响应报文
11、关闭操作
"""
# 1、导入模块
import socket
import WebServer_app
import sys

# WebServer 简单web服务命令行指定参数启动
# 创建类
class WebServer(object):

    # 初始化方法
    def __init__(self, port):
        # 2、创建套接字
        tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 3、设置地址重用
        tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        # 4、绑定端口
        tcp_server_socket.bind(("", port))
        # 5、设置监听,让套接字由主动变为被动接收
        tcp_server_socket.listen(128)
        self.tcp_server_socket = tcp_server_socket

    def start(self):
        # 启动web服务器
        print("Web服务器已经启动,等待客户端连接!")
        # 可循环访问
        while True:
            # 6、接受客户端连接
            new_client_socket, ip_port = self.tcp_server_socket.accept()
            # 调用函数
            # self.new_client_socket = new_client_socket
            self.request_handler(new_client_socket, ip_port)

    # 定义方法 request_handler()
    def request_handler(self, new_client_socket, ip_port):
        # 7、接收客户端浏览器发送的请求协议
        request_data = new_client_socket.recv(1024).decode()
        # print(request_data)
        # 8、判断协议是否为空
        if not request_data:
            print(f"客户端{str(ip_port)}已经下线!")
            new_client_socket.close()
            return
        # 使用py文件夹app模块的application()函数处理
        response_data = WebServer_app.application("D:/dist", request_data)
        # 10、发送响应报文
        new_client_socket.send(response_data)
        # 11、关闭当前连接
        new_client_socket.close()

def main():
    """主函数段"""
    """
    命令行指定参数启动
    1、导入sys模块
    2、获取系统传递到程序的参数
    3、判断参数格式是否正确
    4、判断端口号是否是一个数字
    5、获取端口号
    6、在启动的web服务器的时候,使用指定的端口
    """
    # 获取系统传递到程序的参数
    params_list = sys.argv
    print(params_list)
    if len(params_list) == 1:
        port = 8080
    else:
        # 判断参数格式是否正确
        if len(params_list) != 2:
            print(f"指定的参数格式错误!正确格式:python3 xxx.py 端口号")
            return
        #判断端口号是否是一个数字
        if not params_list[1].isdigit():
            print("启动失败,端口号必须是一个纯数字")
            return
        port = int(params_list[1])
    # 创建WebServer类的对象
    # 对象.start() 启动Web服务器
    ws = WebServer(port)
    ws.start()

if __name__ == '__main__':
    main()

# 指定端口运行: python.exe .\进阶\py\WebServer_cli.py 8000
# 默认端口运行: python.exe .\进阶\py\WebServer_cli.py
# 进阶\py\WebServer\WebServer_utils.py
def create_http_response(status, response_body):
    # 9、拼接响应的报文
    # 9.1 响应行
    response_line = "HTTP/1.1 %s\r\n" % status
    # 9.2 响应头
    response_header = "Server:Python20WS/2.1\r\n"
    response_header +=  "Content-Type: text/html\r\n"
    # 9.3 响应空行
    response_blank = "\r\n"
    # 9.5 响应报文拼接
    response_data = response_line.encode() + response_header.encode() + response_blank.encode() + response_body

    return response_data
# 进阶\py\WebServer\WebServer.py
#!/usr/bin/python
"""
1、导入模块
2、创建套接字
3、设置地址重用
4、绑定端口
5、设置监听,让套接字由主动变为被动接收
6、接受客户端连接  定义函数 request_handler()
7、接收客户端浏览器发送的请求协议
8、判断协议是否为空
9、拼接响应的报文
10、发送响应报文
11、关闭操作
"""
# 1、导入模块
import socket
import WebServer_app

# 创建类
class WebServer(object):

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

    def start(self):
        # 启动web服务器
        # 可循环访问
        while True:
            # 6、接受客户端连接
            new_client_socket, ip_port = self.tcp_server_socket.accept()
            # 调用函数
            # self.new_client_socket = new_client_socket
            self.request_handler(new_client_socket, ip_port)

    # 定义方法 request_handler()
    def request_handler(self, new_client_socket, ip_port):
        # 7、接收客户端浏览器发送的请求协议
        request_data = new_client_socket.recv(1024).decode()
        # print(request_data)
        # 8、判断协议是否为空
        if not request_data:
            print(f"客户端{str(ip_port)}已经下线!")
            new_client_socket.close()
            return
        # 使用py文件夹app模块的application()函数处理
        response_data = WebServer_app.application("D:/dist", request_data)
        # 10、发送响应报文
        new_client_socket.send(response_data)
        # 11、关闭当前连接
        new_client_socket.close()

def main():
    """主函数段"""
    # 创建WebServer类的对象
    # 对象.start() 启动Web服务器
    ws = WebServer()
    ws.start()

if __name__ == '__main__':
    main()
# 进阶\py\WebServer\WSgame_多进程.py
"""
1、导入模块
2、创建套接字
3、设置地址重用
4、绑定端口
5、设置监听,让套接字由主动变为被动接收
6、接受客户端连接  定义函数 request_handler()
7、接收客户端浏览器发送的请求协议
8、判断协议是否为空
9、拼接响应的报文
10、发送响应报文
11、关闭操作
"""
# 1、导入模块
import socket
import WebServer_app
import sys
import multiprocessing

"""
1、在类的初始化方法中配置当前当前的项目
{"2048":"./2048", "植物大战僵尸v1":"./zwdzjs-v1", ...}
2、给类增加一个初始化项目配置的方法 init_projects()
2.1  显示所有可以发布的游戏 菜单
2.2  接收用户的选择
2.3  根据用户的选择发布指定的项目 (保存用户选择的游戏对应的本地目录)
3、更改Web服务器打开的文件目录
"""

# WebServer 简单web服务命令行指定参数启动
# 创建类
class WebServer(object):

    # 初始化方法
    def __init__(self, port):
        # 2、创建套接字
        tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 3、设置地址重用
        tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        # 4、绑定端口
        tcp_server_socket.bind(("", port))
        # 5、设置监听,让套接字由主动变为被动接收
        tcp_server_socket.listen(128)
        self.tcp_server_socket = tcp_server_socket

        # 定义实例属性,保存要发布的项目路径
        self.current_dir = ""
        # 定义类的实例属性,projects_dict初始化为空
        self.projects_dict = dict()
        #                      key                    value
        self.projects_dict['植物大战僵尸-普通版'] = "zwdzjs-v1"
        self.projects_dict['植物大战僵尸-外挂版'] = "zwdzjs-v2"
        self.projects_dict['保卫萝卜'] = "tafang"
        self.projects_dict['2048'] = "2048"
        self.projects_dict['读心术'] = "dxs"

        # 调用初始化游戏项目的方法
        self.init_projects()

    # 2、给类增加一个初始化项目配置的方法 init_projects()
    def init_projects(self):
        # 2.1  显示所有可以发布的游戏 菜单
        # 取出字典的keys 并转换为列表
        keys_list = list(self.projects_dict.keys())
        # print(keys_list)
        # print(list(enumerate(keys_list)))
        # 遍历显示所有的keys  使用enumerate()方法将列表组合为一个索引序列
        for index, game_name in enumerate(keys_list):
            print(f"{index}.{game_name}")
        # 2.2  接收用户的选择
        sel_no = int(input("请选择要发布的游戏序号:\n"))
        # 2.3  根据用户的选择发布指定的项目 (保存用户选择的游戏对应的本地目录)
        # 根据用户的选择得到游戏的名称
        key = keys_list[sel_no]
        # 根据字的key得到游戏项目的路径
        self.current_dir = self.projects_dict[key]
        # print(key,current_dir)

    def start(self):
        # 启动web服务器
        print("Web服务器已经启动,等待客户端连接!")
        # 可循环访问
        while True:
            # 6、接受客户端连接
            new_client_socket, ip_port = self.tcp_server_socket.accept()
            # 调用函数
            # self.new_client_socket = new_client_socket
            # self.request_handler(new_client_socket, ip_port)
            # 创建子进程对象
            process1 = multiprocessing.Process(target=self.request_handler, args=(new_client_socket, ip_port))
            process1.start()

            # 子进程运行会拷贝主进程的资源,new_client_socket引用计数变为2,request_handler函数运行结束后del引用计数为1,需要继续关闭一次释放对象
            new_client_socket.close()

    # 定义方法 request_handler()
    def request_handler(self, new_client_socket, ip_port):
        # 7、接收客户端浏览器发送的请求协议
        request_data = new_client_socket.recv(1024).decode()
        # print(request_data)
        # 8、判断协议是否为空
        if not request_data:
            print(f"客户端{str(ip_port)}已经下线!")
            new_client_socket.close()
            return
        # 使用py文件夹app模块的application()函数处理
        response_data = WebServer_app.application_game(f"D:/python-study-master/day05/{self.current_dir}", request_data)
        # 10、发送响应报文
        new_client_socket.send(response_data)
        # 11、关闭当前连接
        new_client_socket.close()

def main():
    """主函数段"""
    """
    命令行指定参数启动
    1、导入sys模块
    2、获取系统传递到程序的参数
    3、判断参数格式是否正确
    4、判断端口号是否是一个数字
    5、获取端口号
    6、在启动的web服务器的时候,使用指定的端口
    """
    # 获取系统传递到程序的参数
    params_list = sys.argv
    print(params_list)
    if len(params_list) == 1:
        port = 8080
    else:
        # 判断参数格式是否正确
        if len(params_list) != 2:
            print(f"指定的参数格式错误!正确格式:python3 xxx.py 端口号")
            return
        #判断端口号是否是一个数字
        if not params_list[1].isdigit():
            print("启动失败,端口号必须是一个纯数字")
            return
        port = int(params_list[1])
    # 创建WebServer类的对象
    # 对象.start() 启动Web服务器
    ws = WebServer(port)
    ws.start()

if __name__ == '__main__':
    main()

# 指定端口运行: python.exe WSgame.py 8000
# 默认端口运行: python.exe WSgame.py
# 进阶\py\WebServer\WSgame_多线程.py
"""
1、导入模块
2、创建套接字
3、设置地址重用
4、绑定端口
5、设置监听,让套接字由主动变为被动接收
6、接受客户端连接  定义函数 request_handler()
7、接收客户端浏览器发送的请求协议
8、判断协议是否为空
9、拼接响应的报文
10、发送响应报文
11、关闭操作
"""
# 1、导入模块
import socket
import WebServer_app
import sys
import threading

"""
1、在类的初始化方法中配置当前当前的项目
{"2048":"./2048", "植物大战僵尸v1":"./zwdzjs-v1", ...}
2、给类增加一个初始化项目配置的方法 init_projects()
2.1  显示所有可以发布的游戏 菜单
2.2  接收用户的选择
2.3  根据用户的选择发布指定的项目 (保存用户选择的游戏对应的本地目录)
3、更改Web服务器打开的文件目录
"""

# WebServer 简单web服务命令行指定参数启动
# 创建类
class WebServer(object):

    # 初始化方法
    def __init__(self, port):
        # 2、创建套接字
        tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 3、设置地址重用
        tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        # 4、绑定端口
        tcp_server_socket.bind(("", port))
        # 5、设置监听,让套接字由主动变为被动接收
        tcp_server_socket.listen(128)
        self.tcp_server_socket = tcp_server_socket

        # 定义实例属性,保存要发布的项目路径
        self.current_dir = ""
        # 定义类的实例属性,projects_dict初始化为空
        self.projects_dict = dict()
        #                      key                    value
        self.projects_dict['植物大战僵尸-普通版'] = "zwdzjs-v1"
        self.projects_dict['植物大战僵尸-外挂版'] = "zwdzjs-v2"
        self.projects_dict['保卫萝卜'] = "tafang"
        self.projects_dict['2048'] = "2048"
        self.projects_dict['读心术'] = "dxs"

        # 调用初始化游戏项目的方法
        self.init_projects()

    # 2、给类增加一个初始化项目配置的方法 init_projects()
    def init_projects(self):
        # 2.1  显示所有可以发布的游戏 菜单
        # 取出字典的keys 并转换为列表
        keys_list = list(self.projects_dict.keys())
        # print(keys_list)
        # print(list(enumerate(keys_list)))
        # 遍历显示所有的keys  使用enumerate()方法将列表组合为一个索引序列
        for index, game_name in enumerate(keys_list):
            print(f"{index}.{game_name}")
        # 2.2  接收用户的选择
        sel_no = int(input("请选择要发布的游戏序号:\n"))
        # 2.3  根据用户的选择发布指定的项目 (保存用户选择的游戏对应的本地目录)
        # 根据用户的选择得到游戏的名称
        key = keys_list[sel_no]
        # 根据字的key得到游戏项目的路径
        self.current_dir = self.projects_dict[key]
        # print(key,current_dir)

    def start(self):
        # 启动web服务器
        print("Web服务器已经启动,等待客户端连接!")
        # 可循环访问
        while True:
            # 6、接受客户端连接
            new_client_socket, ip_port = self.tcp_server_socket.accept()
            # 调用函数
            # self.new_client_socket = new_client_socket
            # self.request_handler(new_client_socket, ip_port)
            thread_request_handler = threading.Thread(target=self.request_handler, args=(new_client_socket, ip_port))
            thread_request_handler.daemon = True
            thread_request_handler.start()

    # 定义方法 request_handler()
    def request_handler(self, new_client_socket, ip_port):
        # 7、接收客户端浏览器发送的请求协议
        request_data = new_client_socket.recv(1024).decode()
        # print(request_data)
        # 8、判断协议是否为空
        if not request_data:
            print(f"客户端{str(ip_port)}已经下线!")
            new_client_socket.close()
            return
        # 使用py文件夹app模块的application()函数处理
        response_data = WebServer_app.application_game(f"D:/python-study-master/day05/{self.current_dir}", request_data)
        # 10、发送响应报文
        new_client_socket.send(response_data)
        # 11、关闭当前连接
        new_client_socket.close()

def main():
    """主函数段"""
    """
    命令行指定参数启动
    1、导入sys模块
    2、获取系统传递到程序的参数
    3、判断参数格式是否正确
    4、判断端口号是否是一个数字
    5、获取端口号
    6、在启动的web服务器的时候,使用指定的端口
    """
    # 获取系统传递到程序的参数
    params_list = sys.argv
    print(params_list)
    if len(params_list) == 1:
        port = 8080
    else:
        # 判断参数格式是否正确
        if len(params_list) != 2:
            print(f"指定的参数格式错误!正确格式:python3 xxx.py 端口号")
            return
        #判断端口号是否是一个数字
        if not params_list[1].isdigit():
            print("启动失败,端口号必须是一个纯数字")
            return
        port = int(params_list[1])
    # 创建WebServer类的对象
    # 对象.start() 启动Web服务器
    ws = WebServer(port)
    ws.start()

if __name__ == '__main__':
    main()

# 指定端口运行: python.exe WSgame.py 8000
# 默认端口运行: python.exe WSgame.py
# 进阶\py\WebServer\WSgame_协程.py
"""
1、导入模块
2、创建套接字
3、设置地址重用
4、绑定端口
5、设置监听,让套接字由主动变为被动接收
6、接受客户端连接  定义函数 request_handler()
7、接收客户端浏览器发送的请求协议
8、判断协议是否为空
9、拼接响应的报文
10、发送响应报文
11、关闭操作
"""
# 1、导入模块
import socket
import WebServer_app
import sys
import threading
import gevent
from gevent import monkey
monkey.patch_all()

"""
1、在类的初始化方法中配置当前当前的项目
{"2048":"./2048", "植物大战僵尸v1":"./zwdzjs-v1", ...}
2、给类增加一个初始化项目配置的方法 init_projects()
2.1  显示所有可以发布的游戏 菜单
2.2  接收用户的选择
2.3  根据用户的选择发布指定的项目 (保存用户选择的游戏对应的本地目录)
3、更改Web服务器打开的文件目录
"""

# WebServer 简单web服务命令行指定参数启动
# 创建类
class WebServer(object):

    # 初始化方法
    def __init__(self, port):
        # 2、创建套接字
        tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 3、设置地址重用
        tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        # 4、绑定端口
        tcp_server_socket.bind(("", port))
        # 5、设置监听,让套接字由主动变为被动接收
        tcp_server_socket.listen(128)
        self.tcp_server_socket = tcp_server_socket

        # 定义实例属性,保存要发布的项目路径
        self.current_dir = ""
        # 定义类的实例属性,projects_dict初始化为空
        self.projects_dict = dict()
        #                      key                    value
        self.projects_dict['植物大战僵尸-普通版'] = "zwdzjs-v1"
        self.projects_dict['植物大战僵尸-外挂版'] = "zwdzjs-v2"
        self.projects_dict['保卫萝卜'] = "tafang"
        self.projects_dict['2048'] = "2048"
        self.projects_dict['读心术'] = "dxs"

        # 调用初始化游戏项目的方法
        self.init_projects()

    # 2、给类增加一个初始化项目配置的方法 init_projects()
    def init_projects(self):
        # 2.1  显示所有可以发布的游戏 菜单
        # 取出字典的keys 并转换为列表
        keys_list = list(self.projects_dict.keys())
        # print(keys_list)
        # print(list(enumerate(keys_list)))
        # 遍历显示所有的keys  使用enumerate()方法将列表组合为一个索引序列
        for index, game_name in enumerate(keys_list):
            print(f"{index}.{game_name}")
        # 2.2  接收用户的选择
        sel_no = int(input("请选择要发布的游戏序号:\n"))
        # 2.3  根据用户的选择发布指定的项目 (保存用户选择的游戏对应的本地目录)
        # 根据用户的选择得到游戏的名称
        key = keys_list[sel_no]
        # 根据字的key得到游戏项目的路径
        self.current_dir = self.projects_dict[key]
        # print(key,current_dir)

    def start(self):
        # 启动web服务器
        print("Web服务器已经启动,等待客户端连接!")
        # 可循环访问
        while True:
            # 6、接受客户端连接
            new_client_socket, ip_port = self.tcp_server_socket.accept()
            # 调用协程函数
            g = gevent.spawn(self.request_handler, new_client_socket, ip_port)
            # g.join()   主线程循环不会退出,不需要join()

    # 定义方法 request_handler()
    def request_handler(self, new_client_socket, ip_port):
        # 7、接收客户端浏览器发送的请求协议
        request_data = new_client_socket.recv(1024).decode()
        # print(request_data)
        # 8、判断协议是否为空
        if not request_data:
            print(f"客户端{str(ip_port)}已经下线!")
            new_client_socket.close()
            return
        # 使用py文件夹app模块的application()函数处理
        response_data = WebServer_app.application_game(f"D:/python-study-master/day05/{self.current_dir}", request_data)
        # 10、发送响应报文
        new_client_socket.send(response_data)
        # 11、关闭当前连接
        new_client_socket.close()

def main():
    """主函数段"""
    """
    命令行指定参数启动
    1、导入sys模块
    2、获取系统传递到程序的参数
    3、判断参数格式是否正确
    4、判断端口号是否是一个数字
    5、获取端口号
    6、在启动的web服务器的时候,使用指定的端口
    """
    # 获取系统传递到程序的参数
    params_list = sys.argv
    print(params_list)
    if len(params_list) == 1:
        port = 8080
    else:
        # 判断参数格式是否正确
        if len(params_list) != 2:
            print(f"指定的参数格式错误!正确格式:python3 xxx.py 端口号")
            return
        #判断端口号是否是一个数字
        if not params_list[1].isdigit():
            print("启动失败,端口号必须是一个纯数字")
            return
        port = int(params_list[1])
    # 创建WebServer类的对象
    # 对象.start() 启动Web服务器
    ws = WebServer(port)
    ws.start()

if __name__ == '__main__':
    main()

# 指定端口运行: python.exe WSgame.py 8000
# 默认端口运行: python.exe WSgame.py
# 进阶\py\WebServer\WSgame.py
"""
1、导入模块
2、创建套接字
3、设置地址重用
4、绑定端口
5、设置监听,让套接字由主动变为被动接收
6、接受客户端连接  定义函数 request_handler()
7、接收客户端浏览器发送的请求协议
8、判断协议是否为空
9、拼接响应的报文
10、发送响应报文
11、关闭操作
"""
# 1、导入模块
import socket
import WebServer_app
import sys

"""
1、在类的初始化方法中配置当前当前的项目
{"2048":"./2048", "植物大战僵尸v1":"./zwdzjs-v1", ...}
2、给类增加一个初始化项目配置的方法 init_projects()
2.1  显示所有可以发布的游戏 菜单
2.2  接收用户的选择
2.3  根据用户的选择发布指定的项目 (保存用户选择的游戏对应的本地目录)
3、更改Web服务器打开的文件目录
"""

# WebServer 简单web服务命令行指定参数启动
# 创建类
class WebServer(object):

    # 初始化方法
    def __init__(self, port):
        # 2、创建套接字
        tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 3、设置地址重用
        tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        # 4、绑定端口
        tcp_server_socket.bind(("", port))
        # 5、设置监听,让套接字由主动变为被动接收
        tcp_server_socket.listen(128)
        self.tcp_server_socket = tcp_server_socket

        # 定义实例属性,保存要发布的项目路径
        self.current_dir = ""
        # 定义类的实例属性,projects_dict初始化为空
        self.projects_dict = dict()
        #                      key                    value
        self.projects_dict['植物大战僵尸-普通版'] = "zwdzjs-v1"
        self.projects_dict['植物大战僵尸-外挂版'] = "zwdzjs-v2"
        self.projects_dict['保卫萝卜'] = "tafang"
        self.projects_dict['2048'] = "2048"
        self.projects_dict['读心术'] = "dxs"

        # 调用初始化游戏项目的方法
        self.init_projects()

    # 2、给类增加一个初始化项目配置的方法 init_projects()
    def init_projects(self):
        # 2.1  显示所有可以发布的游戏 菜单
        # 取出字典的keys 并转换为列表
        keys_list = list(self.projects_dict.keys())
        # print(keys_list)
        # print(list(enumerate(keys_list)))
        # 遍历显示所有的keys  使用enumerate()方法将列表组合为一个索引序列
        for index, game_name in enumerate(keys_list):
            print(f"{index}.{game_name}")
        # 2.2  接收用户的选择
        sel_no = int(input("请选择要发布的游戏序号:\n"))
        # 2.3  根据用户的选择发布指定的项目 (保存用户选择的游戏对应的本地目录)
        # 根据用户的选择得到游戏的名称
        key = keys_list[sel_no]
        # 根据字的key得到游戏项目的路径
        self.current_dir = self.projects_dict[key]
        # print(key,current_dir)

    def start(self):
        # 启动web服务器
        print("Web服务器已经启动,等待客户端连接!")
        # 可循环访问
        while True:
            # 6、接受客户端连接
            new_client_socket, ip_port = self.tcp_server_socket.accept()
            # 调用函数
            # self.new_client_socket = new_client_socket
            self.request_handler(new_client_socket, ip_port)

    # 定义方法 request_handler()
    def request_handler(self, new_client_socket, ip_port):
        # 7、接收客户端浏览器发送的请求协议
        request_data = new_client_socket.recv(1024).decode()
        # print(request_data)
        # 8、判断协议是否为空
        if not request_data:
            print(f"客户端{str(ip_port)}已经下线!")
            new_client_socket.close()
            return
        # 使用py文件夹app模块的application()函数处理
        response_data = WebServer_app.application_game(f"D:/python-study-master/day05/{self.current_dir}", request_data)
        # 10、发送响应报文
        new_client_socket.send(response_data)
        # 11、关闭当前连接
        new_client_socket.close()

def main():
    """主函数段"""
    """
    命令行指定参数启动
    1、导入sys模块
    2、获取系统传递到程序的参数
    3、判断参数格式是否正确
    4、判断端口号是否是一个数字
    5、获取端口号
    6、在启动的web服务器的时候,使用指定的端口
    """
    # 获取系统传递到程序的参数
    params_list = sys.argv
    print(params_list)
    if len(params_list) == 1:
        port = 8080
    else:
        # 判断参数格式是否正确
        if len(params_list) != 2:
            print(f"指定的参数格式错误!正确格式:python3 xxx.py 端口号")
            return
        #判断端口号是否是一个数字
        if not params_list[1].isdigit():
            print("启动失败,端口号必须是一个纯数字")
            return
        port = int(params_list[1])
    # 创建WebServer类的对象
    # 对象.start() 启动Web服务器
    ws = WebServer(port)
    ws.start()

if __name__ == '__main__':
    main()

# 指定端口运行: python.exe WSgame.py 8000
# 默认端口运行: python.exe WSgame.py