目录

 一、面向对象封装

二、给服务器加上命令行参数

三、植物大战僵尸小游戏服务器 


 一、面向对象封装

        在上一篇博客基础上进行面向对象封装。

代码:

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()

结果:

python socket响应请求_http

 

python socket响应请求_python socket响应请求_02

 

三、植物大战僵尸小游戏服务器 

项目结构:

python socket响应请求_socket_03

 

 服务端代码:

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()

效果:

python socket响应请求_客户端_04

python socket响应请求_http_05

 

 前端代码下载地址:

原生JS实现的h5小游戏-植物大战僵尸