08-Python实现网游服务器

目标

  • 能够利用Web服务器选择发布Web项目

1. 功能分析

1、用户使用浏览器打开指定地址

2、游戏运行方启动服务器,选择要发布的游戏

3、客户端刷新浏览器即可畅玩新的游戏

game_server

2. 实现思路

1、定义初始化项目的方法

2、定义字典保存项目路径 字典格式:key=项目名称 value=路径

3、循环获取字典中的所有key

4、根据key获取游戏的主目录

5、设置实例属性,保存主目录

6、修改Web服务器的目录为实例属性保存的主目录

3. 核心代码

  • dict() 可以用来创建一个空字典

projects_dict = dict() #定义一个空字典 projects_dict

  • projects_dict.key() 返回值是一个含有字典所有key dick_keys的对象,可以的通过 list(projects_dict.key()) 得到一个列表

keys_list = list(self.projects_dict.keys())

  • enumerate(keys_list) 会把列表组合为一个索引序列

my_list = ['Spring', 'Summer', 'Fall', 'Winter']

list2 = enumerate(my_list) # 将my_list组合成索引序列

print(list2) 结果如下:

[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]
  • Content-Type: text/html 服务器响应头中加入这句话,表示浏览器优先使用html解析服务器返回的内容

4. 代码实现

import socket
from application import app
import sys


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

    # 定义初始化方法
    def __init__(self, port):
        # 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(("", port))
        # 4、开启监听,设置套接字由主动设置为被动
        tcp_server_socket.listen(128)
        # 保存socket 到实例属性中
        self.tcp_server_socket = tcp_server_socket

        # 初始化项目
        self.projects_dict = dict()
        # 初始化当前项目路径
        self.current_dir = ""
        # 初始化字典值
        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()

    def init_projects(self):

        # 1、获取字典所有的key
        dict_keys = tuple(self.projects_dict.keys())
        # print(dict_keys)
        # 2、输出提示信息
        print("请选择要发布的项目:\n")
        # 3、循环输出项目列表
        for index, value in enumerate(dict_keys):
            print("%d.%s" % (index, value))

        # 4、接受用户输入的编号
        sel_num = int(input("请选择要发布的游戏编号:\n"))
        # 5、根据编号得到字典key
        sel_key = dict_keys[sel_num]
        print("已经成功发布游戏[%s],客户端请刷新网页使用!" % sel_key)

        # 6、根据字典key获取当前发布的项目的目录
        # 7、保存项目目录到实例变量中
        self.current_dir = self.projects_dict[sel_key]

    # 定义启动服务器方法
    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(self.current_dir, request_data)

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


def main():

    # 判断参数个数是否合法
    if len(sys.argv) != 2:
        print("启动失败,参数个数错误!正确格式:python xxx.py 8080")
        return

    # 判断端口是否是纯数字
    if not sys.argv[1].isdigit():
        print("启动失败,端口不是数字!")
        return

    # 保存端口
    port = int(sys.argv[1])

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

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


if __name__ == '__main__':
    main()