構造が最も明確なHTTPサーバーserverとバックエンドフレームワーク構築(完全コード/HTTP/ソケット/ウェブページ/同時)


HTTPServerプロジェクト設計ドキュメント
目次
文書ディレクトリ
  • HTTPServerプロジェクト設計ドキュメント
  • ディレクトリ
  • 機能要求
  • httpserver部
  • WebFrame部
  • 需要分析
  • フレーム構築
  • 技術点
  • 技術点--json
  • 技術点-正規表現
  • 技術点--同時処理
  • インタラクティブデータフォーマットプロトコル
  • プログラムコード構造
  • メインモジュール構造
  • serverエンド
  • server
  • config--server
  • webframe端子
  • webframe
  • setting
  • static(非モジュール、静的Webページを格納)
  • url
  • views
  • 完全コード
  • httpserver
  • webframe

  • 機能要件
    httpserverセクション
      http   
      http  
          WebFrame
     WebFrame      
          Response        
    

    WebFrameセクション
     httpserver      
                   
             httpserver
    

    需要分析
    フレームワーク
  • httpserverとアプリケーション処理の分離モード:結合度を低減し、論理独立性(モジュールが論理を処理する)
  • ユーザープロファイル:内部構造をカプセル化し、ユーザーフレンドリー
  • webframe部は、バックエンドフレームワークをシミュレートする処理方法结构最清晰的HTTP服务器server和后端框架搭建(完整代码/HTTP/套接字/网页/并发)_第1张图片 结构最清晰的HTTP服务器server和后端框架搭建(完整代码/HTTP/套接字/网页/并发)_第2张图片の主要ファイル配置構造
  • を採用している.
    project
    httpserver
    WebFrame
    HttpServer.pyサービスエリアメインプログラム
    config httpserver構成
    WebFrame.pyバックエンドメインプログラム
    static静的Webページの保存
    views.pyアプリケーションハンドラ
    urls.py格納ルーティング
    settingsフレームワーク構成
    ぎじゅつてん
  • httpserver部分は両端と通信を確立する必要がある:ブラウザ要求受信と応答応答応答応答応答応答、バックエンドの要求送信/結果受信
  • .
  • webFrame部は多重受信同時要求
  • を採用する.
  • データ転送はjsonフォーマット、python jasn
  • を使用します.
    テクニカルポイント-json
    dict_={"name":"  ","age":20,"height":168,"gender":" "}
    #   :python  ---> json,    python    :dict,list
    jdata=json.dumps(dict_)
    #   :json    ---> python
    py_data=json.loads(jdata)
    

    技術点-正規表現
    re=r"[A-Z]+\s+\S*"
    re=r"(?P[A-Z]+)\s+(?P\S*)"
    

    テクニカルポイント-同時処理
    イニシアチブ
    実装方法
    マルチプロセス
    osモジュールfork()実装マルチプロセス:multiprocessingモジュールProcess実装マルチプロセス:1.個々のエントリ関数に対して個々のプロセス2を開く.カスタムプロセスクラスrunは起動関数を定義し、共通のデータをクラスインスタンス変数にカプセル化できます.
    マルチスレッド
    MultiprocessingモジュールTreadはマルチプロセスを実現する:1.プロセスモジュールの使用方法と同じである.注意pythonスレッドとプロセスの違い
    IO多重化
    IO多重化はIO要求密集型の問題を処理するのに適しており、長期占有サービス処理ロジックに対してはマルチプロセス/スレッドselect–rs,ws,xs=select(rlist,wlist,xlist)rlistで属性IOを傍受し、接続終了後に傍受オブジェクトpoll-fdmap格納ファイル記述子とIOオブジェクト辞書を削除し、registerで傍受オブジェクトepollを追加する--pollの使用方法と同じである.しかし、内部実装メカニズムが異なり、epollの効率が最も高く、エッジトリガを設定することができます.
    httpserver–マルチスレッド
    Webframe–IO多重epoll
    インタラクティブデータフォーマットプロトコル
    httpserver-->webframe  {method:'GET',info:'/'}
    webframe-->httpserver {status:'200',data:'ccccc'}
    

    プログラムコードこうぞう
    しゅモジュールこうぞう
    serverエンド
    server
    きほんきのう
    関数#カンスウ#
    データ相互作用方向
    データフォーマット
    1.httpリクエストの取得
    handle()
    server
    httpリクエスト
    2.httpリクエストの解析
    handle()
    server
    http–>json
    3.WebFrameへのリクエストの送信
    connect_webframe()
    server–>webframe
    json
    4.WebFrameからのフィードバックデータの受信
    connect_webframe()
    server
    json
    5.応答形式の送信クライアントにデータを整理する
    response()
    server–>client
    httpレスポンス
    """
    HttpServer         
    """
    from server.config import *
    # httpserver  
    class HTTPServer():
        #     ,             
        #      
        def create_socket(self):
        #        
        def bind(self):
        #     ,        ,        
        def server_forever(self):
        #        
        def handle(self, connfd):
        #               
        def response(self, connfd, data):
    #     ,               ,         
    def connect_webframe(req):
    
    if __name__ == "__main__":
        httpd = HTTPServer()
        httpd.server_forever()
    

    config–server
    """
    httpserver              
    """
    # [httpserver address]
    HOST="0.0.0.0"
    PORT=8000
    # [Debug]
    DEBUG=1
    # [webframe address]
    frame_ip="127.0.0.1"
    frame_port=8080
    

    Webframe端子
    webframe
    """
     httpserver      
                   
             httpserver
    """
    from setting import *
    from urls import *
    #            
    class Application():
        #       
        def __init__(self):
        #        
        def create_socket(self):
        #     
        def bind(self):
        #    epoll   -->IO      
        def init_epoll(self):
        #     (IO    ,epoll())
        def start(self):
        #       ,      
        def handle(self,connfd):
        #       (  )
        def get_html(self,info):
        #      (    )
        def get_data(self,info):
    if __name__=="__main__":
        app=Application()
        app.start()
    

    setting
    #        
    # [webframe address]
    frame_host="0.0.0.0"
    frame_port=8080
    # [Debug]
    DEBUG=1
    # [static html]
    STATIC_DIR="/home/tarena/leixing/code_of_all/projects/http3d0/frame/static"
    

    static(非モジュール、静的Webページの保存)
    404.html
    index.html
    

    url
    from views import *
    urls={
        #      ,         
        "/time":times,
        "/guonei":guonei,
        "/guowai":guowai
    }
    

    views
    from time import *
    #          
    def times():
        return ctime()
    def guonei():
        return "guo nei news:hao hao hao!"
    def guowai():
        return "guo wai news:can can can!"
    

    完全なコード
    httpserver
    from socket import *
    import os, sys
    from threading import Thread
    import json
    from projects.http3d0.server.config import *
    import re
    
    # httpserver  
    class HTTPServer():
        #     ,             
        def __init__(self):
            self.host = HOST
            self.port = PORT
            self.create_socket()
            self.bind()
        #      
        def create_socket(self):
            self.socketfd = socket()
            self.socketfd.setsockopt(SOL_SOCKET, SO_REUSEADDR, DEBUG)
        #        
        def bind(self):
            self.address = (self.host, self.port)
            self.socketfd.bind(self.address)
        #     ,        ,        
        def server_forever(self):
            self.socketfd.listen(5)
            print("Start httpserver:%d" % self.port)
            while True:
                connfd, addr = self.socketfd.accept()
                client = Thread(target=self.handle, args=(connfd,))
                client.setDaemon(True)
                client.start()
        #        
        def handle(self, connfd):
            #       
            request = connfd.recv(1024).decode()
            #          
            pattern = r"(?P[A-Z]+)\s+(?P/\S*)"
            try:
                # {'method': 'GET', 'info': '/'}  
                env = re.match(pattern, request).groupdict()
            except:
                connfd.close()
                return
            else:
                # data  webframe         
                data = connect_webframe(env)
    
                data = json.loads(data)
                self.response(connfd, data)
        #               
        def response(self, connfd, data):
            # data-->{'sattus':'200','data':'XXX'}
            print(data)
            if data['status'] == '200':
                responseHeaders = "HTTP/1.1 200 OK\r
    "
    responseHeaders += "Content-Type:text/html\r
    "
    responseHeaders += "\r
    "
    responseBody = data['data'] elif data['status'] == '404': responseHeaders = "HTTP/1.1 404 NotFound\r
    "
    responseHeaders += "Content-Type:text/html\r
    "
    responseHeaders += "\r
    "
    responseBody = data['data'] response = responseHeaders + responseBody print("RES:", response) connfd.send(response.encode()) # , , def connect_webframe(req): s = socket() try: s.connect((frame_ip, frame_port)) except Exception as e: print(e) return # json, data = json.dumps(req) s.send(data.encode()) # webframe wfdata = s.recv(10 * 1024 * 1024).decode() return wfdata if __name__ == "__main__": httpd = HTTPServer() httpd.server_forever()

    webframe
    
    from socket import *
    import json
    from setting import *
    import os,sys
    from select import *
    from urls import *
    #            
    class Application():
        #       
        def __init__(self):
            self.host = frame_host
            self.port = frame_port
            self.create_socket()
            self.bind()
            self.init_epoll()
        #        
        def create_socket(self):
            self.appfd=socket()
            self.appfd.setsockopt(SOL_SOCKET,SO_REUSEADDR,DEBUG)
        #     
        def bind(self):
            self.ADDR=(self.host,self.port)
            self.appfd.bind(self.ADDR)
            self.appfd.listen(5)
            print("Listen from port:%d"%self.port)
            
        #    epoll   -->IO      
        def init_epoll(self):
            self.fdmap={}
            self.ep=epoll()
            #      ,        (  IO    )map
            #               
            self.ep.register(self.appfd,EPOLLIN)
            self.fdmap[self.appfd.fileno()]=self.appfd
            
        #     (IO    ,epoll())
        def start(self):
            while True:
                events=self.ep.poll()
                for fileno,event in events:
                    if fileno==self.appfd.fileno():
                        connfd,addr=self.fdmap[fileno].accept()
                        self.ep.register(connfd)
                        self.fdmap[connfd.fileno()]=connfd
                    else:
                        self.handle(self.fdmap[fileno])
                        #     ,      
                        self.ep.unregister(fileno)
                        del self.fdmap[fileno]
                        
        #       ,      
        def handle(self,connfd):
            request=connfd.recv(2048).decode()
            request=json.loads(request)
            print(request)
            if request["method"]=="GET":
                #            
                if request["info"]=="/" or request["info"][-5:]==".html":
                    #       
                    response=self.get_html(request["info"])
                #       ,      
                else:
                    response=self.get_data(request["info"])
            elif request["method"]=="POST":
                pass
    
            #      json      httpserver
            response=json.dumps(response)
            connfd.send(response.encode())
            connfd.close()
        #       (  )
        def get_html(self,info):
            if info=="/":
                filename=STATIC_DIR+"/index.html"
            else:
                filename=STATIC_DIR+info
            try:
                fd=open(filename)
            except:
                f=open(STATIC_DIR+"/404.html")
                return{"status":"404","data":f.read()}
            else:
                return{"status":"200","data":fd.read()}
        #      (    )
        def get_data(self,info):
            for url in urls:
                if info==url:
                    return {"status": "200", "data": urls[info]()}
            return {"status":"404","data":"Request out of range,Only for adults"}
    
    if __name__=="__main__":
        app=Application()
        app.start()