1. 程式人生 > 其它 >簡單web伺服器_簡單Web伺服器-網遊伺服器

簡單web伺服器_簡單Web伺服器-網遊伺服器

技術標籤:簡單web伺服器

可以動態根據使用者的輸入,傳送指定的內容的頁面

主體程式碼

#!/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






執行截圖

08ad311e1c73643cc597aee7bb8a3afd.png
可以在客戶端開啟ip,完響應的遊戲