可以动态根据用户的输入,发送指定的内容的页面
主体代码
#!/usr/bin/env python
# encoding: utf-8
# @Time : 2019/10/10 11:57 AM
# @Author : Li Xinjian
# @File : 12_简单Web服务器_网游服务器.py
"""
1、在类的初始化方法中配置当前的项目
{"2048": "./2048", "植物大战僵尸": "zwdzjs-v1", ...}
2、给类增加一个初始化项目配置的方法 init_project()
2.1 显示所有可以发布的游戏 菜单
2.2 接收用户的选择
2.3 保存用户选择的游戏对应的本地目录
3、更改Web服务器打开的文件目录
"""
import socket
from application import app
import sys
# 目标:封装为类,用start()方法启动服务器
class WebServer(object):
def __init__(self, port):
# 1、导入模块
# 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 = ""
self.project_dict = dict()
self.project_dict["植物大战僵尸-普通版"] = "zwdzjs-v1"
self.project_dict["植物大战僵尸-外挂版"] = "zwdzjs-v2"
self.project_dict["保卫萝卜"] = "tafang"
self.project_dict["2048"] = "2048"
self.project_dict["读心术"] = "dxs"
# 调用初始化游戏项目的方法
self.init_project()
def init_project(self):
# 2.1 显示所有可以发布的游戏菜单
# 取出字典的所有key,转化为列表
keys_list = list(self.project_dict.keys())
# 遍历显示所有的key
# enumerate()会为列表添加索引[(0, ), (1, ), ...]
for index, game_name in enumerate(keys_list):
print(index, game_name)
# 2.2 接收用户的选择
sel_no = int(input("请选择要发布的游戏序号:n"))
# 2.3 保存用户选择的游戏对应的本地目录
# 根据用户的选择,得到游戏的名称
key_name = keys_list[sel_no] # 列表
current_dir = self.project_dict[key_name]
# print(current_dir)
self.current_dir = current_dir
def start(self):
print("Web服务器已经启动...等待客户端连接...")
# 6、接受客户端连接(定义函数request_handler())
while True:
new_client_socket, ip_port = self.tcp_server_socket.accept()
print('新客户来了:{}'.format(str(ip_port)))
self.request_handler(new_client_socket, ip_port)
def request_handler(self, new_client_socket, ip_port):
# 接收信息,并做出响应
# 7、新的套接字接受客户端发送的请求报文
request_data = new_client_socket.recv(1024)
# print(request_data)
# 解析请求报文,返回响应报文
response_data = app.application(new_client_socket, self.current_dir, request_data, ip_port)
# 10、发送响应报文
new_client_socket.send(response_data)
new_client_socket.close()
def main():
# 主函数
"""
1、导入sys模块
2、获取系统传递到程序的参数
3、判断参数格式是否正确
4、判断端口号是否是一个数字
5、获取端口号
6、在启动Web服务器的时候,使用指定的端口
"""
# 2、获取系统传递到程序的参数
params_list = sys.argv
print(params_list)
# 3、判断参数格式是否正确
if len(params_list) != 2:
print("启动失败:参数格式错误!正确格式:python3 xxx.py 端口号")
return
# 4、判断端口号是否是一个数字
if not params_list[1].isdigit():
print("启动失败,端口号不是一个纯数字!")
return
# 5、获取端口号
port = int(params_list[1])
# 6、在启动Web服务器的时候,使用指定的端口
ws = WebServer(port)
ws.start()
if __name__ == '__main__':
main()
app.py代码
#!/usr/bin/env python
# encoding: utf-8
# @Time : 2019/10/10 9:21 AM
# @Author : Li Xinjian
# @File : app.py
from application import utils
def parse_request(new_client_socket, request_data, ip_port):
# 返回请求的资源的路径
# 8、判断协议是否为空
# 如果发送的为空,说明客户端下线
if len(request_data) == 0:
print('{}客户端已经下线'.format(str(ip_port)))
new_client_socket.close()
return
# 根据客户端浏览器请求的资源路径,返回请求资源
# 1)把请求协议解码(直接传递过来的是二进制),得到请求报文的请求行字符串
request_text = request_data.decode()
# 2) 得到请求行
# 1) 查找第一个rn出现的位置
loc = request_text.find("rn")
# 2) 截取字符串,从开头截取到rn出现的位置
request_line = request_text[:loc]
print(request_line)
# 3) 把请求按空格分割,得到三个部分,需要的是第二个
request_list = request_line.split(" ")
# print(request_list)
# 得到请求资源的路径
file_path = request_list[1]
# 如果直接打开,返回index.html
if file_path == "/":
file_path = "/index.html"
return file_path
def application(new_client_socket, current_dir, request_data, ip_port):
# 处理请求
# 返回资源的路径
file_path = parse_request(new_client_socket, request_data, ip_port)
# 文件夹路径 + 请求的资源路径
resource_path = current_dir + file_path
# 响应主体
try:
with open(resource_path, "rb") as file:
# 把读取的内容返回给客户端
response_body = file.read()
response_data = utils.create_http_response("200 OK", response_body)
except Exception as e:
# 如果不存在,返回提示的错误
response_body = "Not Found. {}".format(str(e))
response_body = response_body.encode()
response_data = utils.create_http_response("404 Not Found", response_body)
# response_body = "HelloWorld"
return response_data
utils.py代码
#!/usr/bin/env python
# encoding: utf-8
# @Time : 2019/10/10 10:18 AM
# @Author : Li Xinjian
# @File : utils.py.py
def create_http_response(status, response_body):
# 拼接报文
# 9、拼接响应报文
# 不为空,返回响应报文
# 响应行
response_line = "HTTP/1.1 {}rn".format(status)
# 响应头
response_head = "Server:Python20WS/2.1rn"
response_head += "Content-Type: text/htmlrn"
# 响应空行
response_blank = "rn"
response_data = (response_line + response_head + response_blank).encode() + response_body
return response_data
运行截图
![d261bbd9b875a5057d941cc195ddcc50.png](https://img-blog.csdnimg.cn/img_convert/d261bbd9b875a5057d941cc195ddcc50.png)