HTTPserver v3.0 版本項目

項目介紹

模擬使用 socket  多線程 / io多路複用 實現一個簡單的 httpserver 和 webframe 交互的項目程序 html

指望能夠實現簡單的 以 http 協議爲標準的 和瀏覽器 / 前端框架的 數據交互前端

以及 實現簡單的 前端框架模型 python

項目需求分析

項目分爲兩部分 httpserver 部分以及 webframe 部分web

HTTPserver 部分json

1. 獲取 http 請求後端

2. 解析 http 請求瀏覽器

3. 將請求發送給 WebFrame前端框架

4. 從 WebFrame 接收數據信息服務器

5. 將數據信息組織爲 Response 發送給客戶端多線程

WebFrame 部分

1. 從 httpserver 獲取具體請求

2. 根據請求進行邏輯或者數據處理 (簡單處理, 這裏不會過度細緻)

3. 將數據資源發送給 httpserver

兩部分整合後應實現的程度

1. httpserver 與應用程序分離, 各自獨立

2. 獨立開發, 下降互相干擾, 採用各自的配置模式

3. 在後端應用程序中優化數據的處理模型 (暫時就先不作了)

高併發需求處理

1. 多線程

2. IO 多路複用

項目實現

項目結構

 

 項目流程

 

項目源碼

httpserver 部分

httpserver.py

內部實現功能

1. 做爲瀏覽器的 socket_server 須要建立------>服務器套接字 (配合多線程)

2. 接收瀏覽器的 請求進行處理 ------> 處理函數

3. 做爲 webframe 的 socket_client 須要建立------->客戶端套接字

4. 向 webframe 發送請求 -------> 處理函數 

#!/user/bin/env python3
# coding=utf8
"""
AID httpserver v3.0
"""

from socket import *
import sys
import json
from threading import Thread

# 導入配置信息
from httpserver_config import *


# 向 frame 發送請求
def connect_frame(**kwargs):
    s = socket()
    try:
        s.connect(frame_address)
    except Exception as e:
        print(e)
        return
    # 將請求發送給 frame
    s.send(json.dumps(kwargs).encode())
    data = s.recv(4096).decode()
    return data


# 封裝 httpserver 基本功能
class HTTPserver(object):
    def __init__(self, address):
        self.address = address
        self.create_socket()
        self.bind(address)

    # 建立套接字
    def create_socket(self):
        self.sockfd = socket()
        self.sockfd.setsockopt(SOL_SOCKET, SO_REUSEADDR, DEBUG)

    # 綁定監聽地址和端口
    def bind(self, address):
        self.ip = address[0]
        self.port = address[1]
        self.sockfd.bind(address)

    #  啓動服務
    def serve_forever(self):
        self.sockfd.listen(10)
        print("Listen the port %d ..." % self.port)
        while True:
            try:
                connfd, addr = self.sockfd.accept()
                print("Connect from", addr)
            except KeyboardInterrupt:
                self.sockfd.close()
                sys.exit("退出 httpserver 服務")
            except Exception as e:
                print(e)
                continue
            client = Thread(target=self.handle, args=(connfd,))
            client.setDaemon(True)
            client.start()

    # 處理瀏覽器的 http 請求
    def handle(self, connfd):
        request = connfd.recv(4096)
        # 處理客戶端斷開
        if not request:
            connfd.close()
            return
        request_lines = request.splitlines()
        # 獲取請求行
        request_lines = request_lines[0].decode("utf-8")
        print(request_lines)
        # 這裏能夠使用正則固然更好, 可是目前來講無大用
        # 獲取請求方法, 請求內容
        tmp = request_lines.split(" ")
        method = tmp[0]
        path_info = tmp[1]

        data = connect_frame(method=method, path_info=path_info)

        self.response(connfd, data)

    #  處理返回的數據內容
    def response(self, connfd, data):

        # 根據狀況組織響應
        if data != "404":
            response_headlers = "HTTP/1.1 200 OK\r\n"
        else:
            response_headlers = "HTTP/1.1 404 Not Found\r\n"

        response_headlers += '\r\n'
        response_body = data
        response = response_headlers + response_body
        connfd.send(response.encode())
        connfd.close()


httpd = HTTPserver(ADDR)
httpd.serve_forever()  # 啓動服務程序

 httpserver_config.py

htttpserver 的配置文件相關

"""
HTTPserver 配置文件, 用戶填寫基本的必要信息
"""

# HTTPserver
HOST = "0.0.0.0"
PORT = 8000
ADDR = (HOST, PORT)

# debug 設置爲 True 表示調試
DEBUG = True

# 配合 WebFrame 地址
frame_ip = "127.0.0.1"
frame_port = 8080
frame_address = (frame_ip, frame_port)

webframe 部分

webframe.py 

內部實現功能

1. 做爲 httpserver 的服務端處理其請求 ----> 建立 socket_server ( IO多路複用 select 方式 )

2. 處理請求 ---->  對具體的 url 具體分支處理函數

#!/user/bin/env python3
# coding=utf8

"""
模擬網站後端應用處理程序
httpserver v3.0
"""

from socket import *
import select
import json

# 導入配置文件
from settings import *
from views import *


# 建立應用類, 用於具體處理請求
class Application(object):
    def __init__(self):
        self.ip = frame_address[0]
        self.port = frame_address[1]
        self.sockfd = socket()
        self.sockfd.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        self.sockfd.bind(frame_address)

    def start(self):
        self.sockfd.listen(5)
        print("Listen the port %d" % self.port)
        rlist = [self.sockfd]
        wlist = []
        xlist = []
        while True:
            rs, ws, xs = select.select(rlist, wlist, xlist)
            # 循環檢查是否就緒
            for r in rs:
                #  判斷加入 關注列表
                if r is self.sockfd:
                    connfd, addr = r.accept()
                    rlist.append(connfd)
                else:
                    # 接受 httpserver 的請求
                    request = r.recv(2048).decode()
                    if not request:
                        rlist.remove(r)
                        continue
                    self.handle(r, request)

    # 處理請求
    def handle(self, connfd, request):
        request = json.loads(request)
        method = request["method"]
        path_info = request["path_info"]
        print(path_info)
        if method == "GET":
            if path_info == "/" or path_info[-5:] == ".html":
                data = self.get_html(path_info)
            else:
                data = self.get_data(path_info)
        elif method == "POST":
            pass
        # 獲得網頁內容就發送 未獲得就發送404
        if data:
            connfd.send(data.encode())
        else:
            connfd.send(b"404")

    # 處理網頁
    def get_html(self, path_info):
        if path_info == "/":
            get_file = STATIC_DIR + "/index.html"
        else:
            get_file = STATIC_DIR + path_info
        try:
            fd = open(get_file, encoding="utf8")
            data = fd.read()
        except IOError:
            return
        return data

    # 處理數據
    def get_data(self, path_info):
        for url, func in urls:
            if path_info == url:
                return func()
        return "404"


app = Application()
app.start()  # 啓動後端框架服務

settings.py

框架的配置文件

以及 自定義的函數對應方法的映射配置 相似於 Django 的路由系統

"""
Frame 程序配置文件
"""
from views import *


# 配置框架地址
frame_ip = "0.0.0.0"
frame_port = 8080
frame_address = (frame_ip, frame_port)

# 靜態網頁位置
STATIC_DIR = "./static"

#
urls = [
    ("/time", show_time),
    ("/hello", say_hello)
]

views.py

自定義的返回視圖函數, 相似於 Django 的 視圖系統

import time


def show_time():
    return time.ctime()


def say_hello():
    return "Hello world"
相關文章
相關標籤/搜索