構造が最も明確なHTTPサーバーserverとバックエンドフレームワーク構築(完全コード/HTTP/ソケット/ウェブページ/同時)
44909 ワード
HTTPServerプロジェクト設計ドキュメント
目次
文書ディレクトリ HTTPServerプロジェクト設計ドキュメント ディレクトリ 機能要求 httpserver部 WebFrame部 需要分析 フレーム構築 技術点 技術点--json 技術点-正規表現 技術点--同時処理 インタラクティブデータフォーマットプロトコル プログラムコード構造 メインモジュール構造 serverエンド server config--server webframe端子 webframe setting static(非モジュール、静的Webページを格納) url views 完全コード httpserver webframe
機能要件
httpserverセクション
WebFrameセクション
需要分析
フレームワーク httpserverとアプリケーション処理の分離モード:結合度を低減し、論理独立性(モジュールが論理を処理する) ユーザープロファイル:内部構造をカプセル化し、ユーザーフレンドリー webframe部は、バックエンドフレームワークをシミュレートする処理方法 の主要ファイル配置構造 を採用している.
project
httpserver
WebFrame
HttpServer.pyサービスエリアメインプログラム
config httpserver構成
WebFrame.pyバックエンドメインプログラム
static静的Webページの保存
views.pyアプリケーションハンドラ
urls.py格納ルーティング
settingsフレームワーク構成
ぎじゅつてん httpserver部分は両端と通信を確立する必要がある:ブラウザ要求受信と応答応答応答応答応答応答、バックエンドの要求送信/結果受信 . webFrame部は多重受信同時要求 を採用する.データ転送はjsonフォーマット、python jasn を使用します.
テクニカルポイント-json
技術点-正規表現
テクニカルポイント-同時処理
イニシアチブ
実装方法
マルチプロセス
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
インタラクティブデータフォーマットプロトコル
プログラムコードこうぞう
しゅモジュールこうぞう
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レスポンス
config–server
Webframe端子
webframe
setting
static(非モジュール、静的Webページの保存)
url
views
完全なコード
httpserver
webframe
目次
文書ディレクトリ
機能要件
httpserverセクション
http
http
WebFrame
WebFrame
Response
WebFrameセクション
httpserver
httpserver
需要分析
フレームワーク
project
httpserver
WebFrame
HttpServer.pyサービスエリアメインプログラム
config httpserver構成
WebFrame.pyバックエンドメインプログラム
static静的Webページの保存
views.pyアプリケーションハンドラ
urls.py格納ルーティング
settingsフレームワーク構成
ぎじゅつてん
テクニカルポイント-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()