CS 即客戶端,服務端編程html
客戶端,服務端之間須要使用Socket ,約定協議,版本(每每使用的協議是TCP或UDP),指定地址和端口,就能夠通訊了。前端
客戶端,服務端傳輸數據,數據就能夠有必定的格式雙方必須先約定好node
BS編程,即Browser Server 開發python
Browser 瀏覽器,一種特殊的客戶端,支持HTTP(s)協議,可以經過URL 向服務器發起請求,等待服務器返回HTML等數據,並在瀏覽器內可視化展現的程序web
Server 支持HTTP(s)協議,可以接受衆多的客戶端發起的http協議請求,通過處理,將HTML 等數據返回給瀏覽器npm
本質上說,BS 是一種特殊的CS,即客戶端必須是一種支持HTTP的協議的且可以解析並渲染HTML的軟件,服務端必須是可以接受多客服端HTTP訪問的服務器軟件。編程
HTTP協議底層基於TCP 協議實現。瀏覽器
二、HTTP協議服務器
Http協議是無狀態協議cookie
同一個客戶端的兩次請求之間沒有任何關係,從服務器端角度來講,它不知道這兩個請求來自同一個客戶端
cookie
鍵值對信息
是一種客服端,服務端傳遞數據的技術
通常來講,cookie信息是在服務器端產生的,返回給客服端的。
瀏覽器發起每一請求時,都會把cookie 信息發給服務器端
服務器端收到瀏覽器發來的cookie信息,處理這些信息,能夠用來判斷此次請求是否和以前的請求有關聯。
客戶端能夠本身設置cookie信息
URL組成
url 能夠說是地址, uniform resource locator 同一資源定位符,每個連接指向一個資源供客戶端訪問
schema://host【:psot】/path/...../[;url-params] [?query-string][#anchor]
例如:經過如下的URL 訪問網頁
http://www.baidu.com/python/index.html?id=5&name=python
訪問靜態資源是,經過上面的這個url訪問的是網站的某個路徑下的index.html 文件,而這個文件對應磁盤上的真實的訪問路徑,就會從磁盤上讀取這個文件並把文件的內容發回瀏覽器端。
schema:協議 -----http https ftp ftps mailto等
通常都是默認80 端口,80 能夠不寫,不然都須要指明,域名會使用DNS 解析,域名會解析成IP才能使用,實際上會對解析後返回的TCP的80 端口發起訪問。
query string (如:?key1=value1&key2=value2)查詢字符串,問號用來和路徑分開,後面key=value形式,且使用&符號分割開
HTTP消息:
消息分爲 Request, Response
Request:瀏覽器向服務器發起的請求
Response:服務器對客服端請求的響應
請求和響應消息都是由請求行,Header消息報頭,Body消息正文組成。
請求:
請求消息行:請求方法Method 請求路徑 協議版本 CRLF
請求方法Method:
GET: 請求獲取URL 對應的資源
POST:提交數據至服務器端
HEAD:和GET相似,不過不返回消息正文
常見傳遞消息的方式:
一、GET方法使用Query String ,搜索欄直接輸入:
http://www.nagedu.com/python/index.html?id=5&name=python
二、POST 方法提交數據
表單:
使用post 提交表單後:
三、URL中自己就包含着信息
http://www.magedu.com/python/istudent/001
響應:
響應消息行:協議版本 狀態碼 描述信息CRLF
status code狀態碼:
重定向:( 訪問兩次)
B <---------> S (301,302)
------------->
無狀態,有鏈接, 短鏈接:
無狀態:指的是服務器沒法知道2次請求之間的聯繫,即便是先後兩次同一個瀏覽器也沒有任何數據可以判斷出是同一個瀏覽器的請求。後來能夠經過cookie session 來判斷
有鏈接:是由於基於TCP協議,是面向鏈接的,須要3次握手,四次斷開
短鏈接:Http 1.1 以前都是一個請求一個鏈接,而TCP 的連接建立銷燬成本高,對服務器有很大的影響,因此以後,支持keep-alive 默認也開啓,一個鏈接打開後,會保持一段時間(可設置),瀏覽器在訪問該服務器就是用這個TCp 鏈接,減輕服務器壓力,提升效率。
WSGI 服務器----wsgiref
wsgiref 是Python提供的一個WSGI 參考實現庫(只能本身測試用,不能用於生產環境)
sdgiref.simple_server 模塊實現一個簡單的WSGI Http 服務器
wsgiref.simple_server.make_server(host, port , app, server_class=WSGIServer,handler_class=WSGIRequestHandler) 啓動一個WSGI 服務器
wsgiref.simple_server.demo_app(environ, start_response) 一個 兩個參數的 函數,小巧完整的WSGI的應用程序的實現。
測試:
結果:
WSGI服務器做用:
WSGI APP 應用程序端
demo_app:源代碼:
測試:可調用對象的實現,都必須返回一個可迭代對象
1 from wsgiref.simple_server import make_server, demo_app 2 ip = '127.0.0.1' 3 port = 8080 4 5 # 原碼:return [stdout.getvalue().encode("utf-8")] 6 rest_str = b'www.jerry.com' 7 8 # # 函數實現 application 9 # def application(environ, start_response): 10 # start_response("200 OK", [('Content-Type','text/plain; charset=utf-8')]) 11 # return [rest_str] 12 13 # 類實現 14 class Application: 15 def __init__(self,environ, start_response): 16 self.env = environ 17 # self.resp = start_response 18 # 必須且只能執行一次 19 start_response("200 OK", [('Content-Type', 'text/plain; charset=utf-8')]) 20 21 def __iter__(self): 22 # self.resp("200 OK", [('Content-Type','text/plain; charset=utf-8')]) 23 yield rest_str 24 25 server = make_server(ip, port, Application) # demo_app 應用程序,可調用 26 27 28 # 類實現 可調用對象 29 class Application: 30 def __call__(self,environ, start_response): 31 start_response("200 OK", [('Content-Type','text/plain; charset=utf-8')]) 32 return [rest_str] 33 34 35 server = make_server(ip, port, Application()) # demo_app 應用程序,可調用 36 37 38 server.serve_forever() # server.handle_request() 執行一次
environ:
environ 是包含HTTP請求信息的dict字典對象( Header 信息,除了首行,都是key: value)
1 ('ALLUSERSPROFILE', 'C:\\ProgramData') 2 ('APPDATA', 'C:\\Users\\Administrator\\AppData\\Roaming') 3 ('COMMONPROGRAMFILES', 'C:\\Program Files\\Common Files') 4 ('COMMONPROGRAMFILES(X86)', 'C:\\Program Files (x86)\\Common Files') 5 ('COMMONPROGRAMW6432', 'C:\\Program Files\\Common Files') 6 ('COMPUTERNAME', 'USER-20180710VW') 7 ('COMSPEC', 'C:\\Windows\\system32\\cmd.exe') 8 ('FP_NO_HOST_CHECK', 'NO') 9 ('GOPATH', 'F:\\goproject') 10 ('GOROOT', 'D:\\go_sdk\\go') 11 ('HOMEDRIVE', 'C:') 12 ('HOMEPATH', '\\Users\\Administrator') 13 ('LOCALAPPDATA', 'C:\\Users\\Administrator\\AppData\\Local') 14 ('LOGONSERVER', '\\\\USER-20180710VW') 15 ('NUMBER_OF_PROCESSORS', '4') 16 ('OS', 'Windows_NT') 17 ('PATH', 'C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;D:\\Git\\cmd;D:\\nodejs\\;D:\\python3.7\\Scripts\\;D:\\python3.7\\;C:\\Users\\Administrator\\AppData\\Roaming\\npm;D:\\Microsoft VS Code\\bin;D:\\go_sdk\\go\\bin') 18 ('PATHEXT', '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC') 19 ('PROCESSOR_ARCHITECTURE', 'AMD64') 20 ('PROCESSOR_IDENTIFIER', 'Intel64 Family 6 Model 60 Stepping 3, GenuineIntel') 21 ('PROCESSOR_LEVEL', '6') 22 ('PROCESSOR_REVISION', '3c03') 23 ('PROGRAMDATA', 'C:\\ProgramData') 24 ('PROGRAMFILES', 'C:\\Program Files') 25 ('PROGRAMFILES(X86)', 'C:\\Program Files (x86)') 26 ('PROGRAMW6432', 'C:\\Program Files') 27 ('PSMODULEPATH', 'C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\Modules\\') 28 ('PUBLIC', 'C:\\Users\\Public') 29 ('PYCHARM_HOSTED', '1') 30 ('PYTHONIOENCODING', 'UTF-8') 31 ('PYTHONPATH', 'E:\\code_pycharm') 32 ('PYTHONUNBUFFERED', '1') 33 ('SESSIONNAME', 'Console') 34 ('SYSTEMDRIVE', 'C:') 35 ('SYSTEMROOT', 'C:\\Windows') 36 ('TEMP', 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp') 37 ('TMP', 'C:\\Users\\ADMINI~1\\AppData\\Local\\Temp') 38 ('USERDOMAIN', 'USER-20180710VW') 39 ('USERNAME', 'Administrator') 40 ('USERPROFILE', 'C:\\Users\\Administrator') 41 ('WINDIR', 'C:\\Windows') 42 ('WINDOWS_TRACING_FLAGS', '3') 43 ('WINDOWS_TRACING_LOGFILE', 'C:\\BVTBin\\Tests\\installpackage\\csilogfile.log') 44 ('_DFX_INSTALL_UNSIGNED_DRIVER', '1') 45 ('SERVER_NAME', 'USER-20180710VW') 46 ('GATEWAY_INTERFACE', 'CGI/1.1') 47 ('SERVER_PORT', '8080') 48 ('REMOTE_HOST', '') 49 ('CONTENT_LENGTH', '') 50 ('SCRIPT_NAME', '') 51 ('SERVER_PROTOCOL', 'HTTP/1.1') 52 ('SERVER_SOFTWARE', 'WSGIServer/0.2') 53 ('REQUEST_METHOD', 'GET') 54 ('PATH_INFO', '/') 55 ('QUERY_STRING', '') 56 ('REMOTE_ADDR', '127.0.0.1') 57 ('CONTENT_TYPE', 'text/plain') 58 ('HTTP_HOST', '127.0.0.1:8080') 59 ('HTTP_CONNECTION', 'keep-alive') 60 ('HTTP_CACHE_CONTROL', 'max-age=0') 61 ('HTTP_UPGRADE_INSECURE_REQUESTS', '1') 62 ('HTTP_USER_AGENT', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36 Maxthon/5.2.4.3000') 63 ('HTTP_ACCEPT', 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8') 64 ('HTTP_DNT', '1') 65 ('HTTP_ACCEPT_ENCODING', 'gzip, deflate') 66 ('HTTP_ACCEPT_LANGUAGE', 'zh-CN') 67 ('wsgi.input', <_io.BufferedReader name=384>) 68 ('wsgi.errors', <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>) 69 ('wsgi.version', (1, 0)) 70 ('wsgi.run_once', False) 71 ('wsgi.url_scheme', 'http') 72 ('wsgi.multithread', True) 73 ('wsgi.multiprocess', False) 74 ('wsgi.file_wrapper', <class 'wsgiref.util.FileWrapper'>)
start_response
它是一個可調用對象, 有3個參數,定義以下:
start_response( status, response_headers, exc_info=None), header部分,(‘ key ’, ' value ')
start_response應該在返回可迭代對象以前嗲用,由於他是 header,return返回的是一個可迭代對象,不必定是一個列表。
服務器程序須要調用符合上述定義的可調用對象APP,傳入 environ, start_response
APP處理後,返回響應頭和可迭代對象正文,由服務器的封裝成 http報文,返回給瀏覽器
測試:
WSGI WEB 服務器:
本質上就是一個TCP 服務器,監聽在特色的端口上
支持HTTP 協議,可以將HTTP請求報文進行解析,可以把響應數據進行HTTP協議的報文封裝並返回瀏覽器
實現了WSGI 協議,該協議約定了和應用恆旭之間的接口,https://www.python.org/dev/peps/pep-0333/
WSGI APP 應用程序:
聽從WSGI協議
自己是一個可調用對象
調用start_response,返回響應頭部
返回包含正文的可迭代對象
WSGI 框架庫,每每 能夠看作加強的更加複雜的Application
WSGI是Web Server Gateway Interface的縮寫。以層的角度來看,WSGI所在層的位置低於CGI。但與CGI不一樣的是WSGI具備很強的伸縮性且能運行於多線程或多進程的環境下,這是由於WSGI只是一份標準並無定義如何去實現。實際上WSGI並不是CGI,由於其位於web應用程序與web服務器之間,而web服務器能夠是CGI,直接以模塊編譯進去,mod_python(注:現一般使用mod_wsgi代替),FastCGI或者是一個定義了WSGI標準的web服務器就像python標準庫提供的獨立WSGI服務器稱爲wsgiref。