目录
在上一篇博客(使用 python socket 向http服务器发送请求并制作http服务器)
基础上进行面向对象封装。
代码:
- import socket
- from threading import Thread
-
- class WebServer(object):
-
- # 初始化方法
- def __init__(self):
- # 创建套接字
- self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-
- # 设置地址重用 SOL_SOCKET表示当前套接字,SO_REUSEADDR表示设置地址重用
- self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
-
- # 绑定端口
- self.tcp_server_socket.bind(("", 8080))
-
- # 设置监听,让套接字由主动变为被动接收
- self.tcp_server_socket.listen(128)
-
- def start(self):
- """ 启动Web服务器 """
- while True:
- # 接收客户端连接 定义函数
- new_client_socket, ip_port = self.tcp_server_socket.accept()
- print("新的客户端%s已连接!" % str(ip_port))
-
- # 接收请求并作出响应
- t1 = Thread(target=self.request_handler, args=(new_client_socket, ip_port))
- t1.start()
-
- def request_handler(self, new_client_socket, ip_port):
- """接收信息,并且做出响应"""
-
- # 接收客户端浏览器发送的请求协议
- request_data = new_client_socket.recv(1024) # 接收请求报文
- # print(request_data)
-
- # 判断协议是否为空
- if not request_data:
- print("%s客户端已下线!" % str(ip_port))
- new_client_socket.close()
- else:
- # 根据客户端浏览器请求的资源路径,返回请求资源
- # 1.把请求协议解码,得到请求报文的字符串
- request_text = request_data.decode()
-
- # 2.得到请求行
- # 2.1 查找 第一个\r\n出现的位置
- loc = request_text.find("\r\n")
-
- # 2.2 截取字符串,从开头截取到 第一个\r\n出现的位置
- request_line = request_text[:loc]
- # print(request_line)
-
- # 2.3 把请求行按照空格拆分,得到列表
- request_line_list = request_line.split(" ")
-
- # 2.4 得到请求资源路径
- file_path = request_line_list[1]
- print("%s 正在请求:%s" % (str(ip_port), file_path))
-
- # 响应行
- response_line = "HTTP/1.1 200 OK\r\n"
-
- # 响应头
- response_header = "Server:Python20WS/2.1\r\n"
-
- # 响应空行
- response_blank = "\r\n"
-
- # 响应主体
- # 返回字符串内容
- # response_body = "Hello World"
-
- # 返回固定页面
- try:
- with open("static" + file_path, "rb") as file:
- response_body = file.read()
- except Exception as e:
- # 重新修改响应行为 404
- 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
-
- # 发送响应报文
- new_client_socket.send((response_data))
-
- # 关闭连接
- new_client_socket.close()
-
- if __name__ == '__main__':
- WS = WebServer()
- WS.start()
- import socket,sys
- from threading import Thread
-
- class WebServer(object):
-
- # 初始化方法
- def __init__(self, port):
- # 创建套接字
- self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-
- # 设置地址重用 SOL_SOCKET表示当前套接字,SO_REUSEADDR表示设置地址重用
- self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
-
- # 绑定端口
- self.tcp_server_socket.bind(("", port))
-
- # 设置监听,让套接字由主动变为被动接收
- self.tcp_server_socket.listen(128)
-
- def start(self):
- """ 启动Web服务器 """
- while True:
- # 接收客户端连接 定义函数
- new_client_socket, ip_port = self.tcp_server_socket.accept()
- print("新的客户端%s已连接!" % str(ip_port))
-
- # 接收请求并作出响应
- t1 = Thread(target=self.request_handler, args=(new_client_socket, ip_port))
- t1.start()
-
- def request_handler(self, new_client_socket, ip_port):
- """接收信息,并且做出响应"""
-
- # 接收客户端浏览器发送的请求协议
- request_data = new_client_socket.recv(1024) # 接收请求报文
- # print(request_data)
-
- # 判断协议是否为空
- if not request_data:
- print("%s客户端已下线!" % str(ip_port))
- new_client_socket.close()
- else:
- # 根据客户端浏览器请求的资源路径,返回请求资源
- # 1.把请求协议解码,得到请求报文的字符串
- request_text = request_data.decode()
-
- # 2.得到请求行
- # 2.1 查找 第一个\r\n出现的位置
- loc = request_text.find("\r\n")
-
- # 2.2 截取字符串,从开头截取到 第一个\r\n出现的位置
- request_line = request_text[:loc]
- # print(request_line)
-
- # 2.3 把请求行按照空格拆分,得到列表
- request_line_list = request_line.split(" ")
-
- # 2.4 得到请求资源路径
- file_path = request_line_list[1]
- print("%s 正在请求:%s" % (str(ip_port), file_path))
-
- # 响应行
- response_line = "HTTP/1.1 200 OK\r\n"
-
- # 响应头
- response_header = "Server:Python20WS/2.1\r\n"
-
- # 响应空行
- response_blank = "\r\n"
-
- # 响应主体
- # 返回字符串内容
- # response_body = "Hello World"
-
- # 返回固定页面
- try:
- with open("static" + file_path, "rb") as file:
- response_body = file.read()
- except Exception as e:
- # 重新修改响应行为 404
- 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
-
- # 发送响应报文
- new_client_socket.send((response_data))
-
- # 关闭连接
- new_client_socket.close()
-
- def main():
- # 获取系统传递到程序的参数
- params_list = sys.argv
- # print(params_list)
-
- # 判断参数个数
- if len(params_list) != 2:
- print("启动失败,正确启动格式:python xxx.py port")
-
- # 判断端口号是否为纯数字
- if not params_list[1].isdigit():
- print("启动失败,端口号应为纯数字")
-
- port = int(params_list[1])
-
- WS = WebServer(port)
- WS.start()
-
- if __name__ == '__main__':
- main()
结果:
项目结构:
服务端代码:
- import socket,sys
-
-
- class WebServer(object):
-
- # 初始化方法
- def __init__(self, port):
- # 创建套接字
- self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-
- # 设置地址重用 SOL_SOCKET表示当前套接字,SO_REUSEADDR表示设置地址重用
- self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
-
- # 绑定端口
- self.tcp_server_socket.bind(("", port))
-
- # 设置监听,让套接字由主动变为被动接收
- self.tcp_server_socket.listen(128)
-
- self.project_dict = {}
- self.project_dict["足球大战僵尸"] = "h5-game-footballVSzombies"
- self.project_dict["植物大战僵尸"] = "h5-game-plantsVSzombies"
-
- self.current_dir = ""
-
- self.init_projects()
-
- def init_projects(self):
- # 显示所有的游戏名称
- key_list = list(self.project_dict.keys()) # 取出字典的key并且转换成列表
- for index, gameName in enumerate(key_list):
- print("%d.%s" % (index, gameName))
-
- # 接收用户的选择
- sel_no = int(input("请选择游戏序号:\n"))
-
- # 根据用户的选择来运行指定游戏
- key = key_list[sel_no]
-
- # 根据key得到项目路径
- self.current_dir = self.project_dict[key]
- print(key, self.current_dir)
-
- def start(self):
- """ 启动Web服务器 """
- print("网游服务器已启动!")
- while True:
- # 接收客户端连接 定义函数
- new_client_socket, ip_port = self.tcp_server_socket.accept()
- print("新的客户端%s已连接!" % str(ip_port))
-
- # 接收请求并作出响应
- self.request_handler(new_client_socket, ip_port)
-
- def request_handler(self, new_client_socket, ip_port):
- """接收信息,并且做出响应"""
-
- # 接收客户端浏览器发送的请求协议
- request_data = new_client_socket.recv(1024) # 接收请求报文
- # print(request_data)
-
- # 判断协议是否为空
- if not request_data:
- print("%s客户端已下线!" % str(ip_port))
- new_client_socket.close()
- else:
- # 根据客户端浏览器请求的资源路径,返回请求资源
- # 1.把请求协议解码,得到请求报文的字符串
- request_text = request_data.decode()
-
- # 2.得到请求行
- # 2.1 查找 第一个\r\n出现的位置
- loc = request_text.find("\r\n")
-
- # 2.2 截取字符串,从开头截取到 第一个\r\n出现的位置
- request_line = request_text[:loc]
- # print(request_line)
-
- # 2.3 把请求行按照空格拆分,得到列表
- request_line_list = request_line.split(" ")
-
- # 2.4 得到请求资源路径
- file_path = request_line_list[1]
- print("%s 正在请求:%s" % (str(ip_port), file_path))
-
- if file_path == "/":
- file_path = "/index.html"
-
- # 响应行
- response_line = "HTTP/1.1 200 OK\r\n"
-
- # 响应头
- response_header = "Server:Python20WS/2.1\r\n"
- # response_header = response_header + "Content-Type: text/html\r\n"
-
- # 响应空行
- response_blank = "\r\n"
-
- # 响应主体
- # 返回字符串内容
- # response_body = "Hello World"
-
- # 返回固定页面
- try:
- with open(self.current_dir + file_path, "rb") as file:
- response_body = file.read()
- except Exception as e:
- # 重新修改响应行为 404
- 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
-
- # 发送响应报文
- new_client_socket.send((response_data))
-
- # 关闭连接
- new_client_socket.close()
-
- def main():
- # 获取系统传递到程序的参数
- params_list = sys.argv
- # print(params_list)
-
- # 判断参数个数
- if len(params_list) != 2:
- print("启动失败,正确启动格式:python xxx.py port")
-
- # 判断端口号是否为纯数字
- if not params_list[1].isdigit():
- print("启动失败,端口号应为纯数字")
-
- port = int(params_list[1])
-
- WS = WebServer(port)
- WS.start()
-
- if __name__ == '__main__':
- main()
效果:
前端代码下载地址: