HTTP、BS架構


Django 底層原理

快捷鍵

  • 方向鍵

    • 方向鍵本鍵如果活動選項是選項按鈕或文件則為移動焦點;
    • 方向鍵 + Win鍵(簡稱Win鍵)使窗口全屏、最小化、靠左半邊、靠右半邊(部分版本不支持);
    • 方向鍵+Shift鍵將連續的文字或文件選中
    • 方向鍵(左右)+Ctrl鍵 在英文單詞或中文詞語間跳躍
    • 方向鍵(上下)+Ctrl鍵 在段落開頭間跳躍
    • 按Home(定位到行首)然后按Shift+End(行尾)或者 然后按Shift+↓ (下一行這個位置)
    • 或者 按End(定位到行尾)然后按Shift+Home
  • ctrl

    • Ctrl+b 粗體 Bold
    • Ctrl+e 居中對齊 Encenter
    • Ctrl+f 查找 Find
    • Ctrl+h 替換 Huan
    • Ctrl+k 超級鏈接 King Link
  • win

    • Win鍵+E打開Windows資源管理器Explorer【即我的電腦、計算機】
    • Win鍵+R:運行
    • Win鍵+Shift+S:Windows 自帶截圖
    • win鍵+PrtScSysRq鍵 快速截屏

HTTP

  • 超文本傳輸協議(英文:HyperText Transfer Protocol,縮寫:HTTP)是一種用於分布式、協作式和超媒體信息系統的應用層協議。HTTP是萬維網WEB的數據通信的基礎。
  • 現今廣泛使用的一個版本——HTTP 1.1(已更新至2.0)

HTTP工作原理

  • HTTP協議定義Web客戶端如何從Web服務器請求Web頁面,以及服務器如何把Web頁面傳送給客戶端。

  • HTTP協議采用了請求/響應模型

  • 客戶端向服務器發送一個請求報文,請求報文包含請求的方法、URL、協議版本、請求頭部和請求數據。服務器以一個狀態行作為響應,響應的內容包括協議的版本、成功或者錯誤代碼、服務器信息、響應頭部和響應數據

  • 響應報文:比如"HTTP/1.1 200 OK"

  • 以下是 HTTP 請求/響應的步驟:

    1. 客戶端連接到Web服務器
      一個HTTP客戶端,通常是瀏覽器,與Web服務器的HTTP端口(默認為80)建立一個TCP套接字連接。例如,http://www.luffycity.com

    2. 發送HTTP請求
      通過TCP套接字,客戶端向Web服務器發送一個文本的請求報文,一個請求報文由請求行、請求頭部、空行和請求數據4部分組成。

    3. 服務器接受請求並返回HTTP響應
      Web服務器解析請求,定位請求資源。服務器將資源復本寫到TCP套接字,由客戶端讀取。一個響應由狀態行、響應頭部、空行和響應數據4部分組成。

    4. 釋放連接TCP連接
      若connection 模式為 close(無連接),則服務器主動關閉TCP連接,客戶端被動關閉連接,釋放TCP連接;若 connection 模式為 keepalive(短連接),則該連接會保持一段時間,在該時間內可以繼續接收請求;

    5. 客戶端瀏覽器解析HTML內容
      客戶端瀏覽器首先解析狀態行,查看表明請求是否成功的狀態代碼。然后解析每一個響應頭,響應頭告知以下為若干字節的HTML文檔和文檔的字符集。客戶端瀏覽器讀取響應數據HTML,根據HTML的語法對其進行格式化,並在瀏覽器窗口中顯示。

    例如:在瀏覽器地址欄鍵入URL,按下回車之后會經歷以下流程:

    1. 瀏覽器向 DNS 服務器請求解析該 URL 中的域名所對應的 IP 地址;
      • 域名(DN)域名服務器(DNS)
      • 域名(英語:Domain Name),又稱網域,是由一串用點分隔的名字組成的Internet上某一台計算機或計算機組的名稱,用於在數據傳輸時對計算機的定位標識(有時也指地理位置)。
      • 由於IP地址具有不方便記憶並且不能顯示地址組織的名稱和性質等缺點,人們設計出了域名,並通過域名服務器DNS,Domain Name System)來將域名和IP地址相互映射,使人更方便地訪問互聯網,而不用去記住能夠被機器直接讀取的IP地址數串
    2. 解析出 IP 地址后,根據該 IP 地址和默認端口 80,和服務器建立TCP連接;
    3. 瀏覽器發出讀取文件(URL 中域名后面部分對應的路徑(文件))的HTTP 請求,該請求報文作為 TCP 三次握手中第三次握手(由客戶端發送)時的報文數據發送給服務器;
    4. 服務器對瀏覽器請求作出響應,並把對應的 html 文本發送給瀏覽器;
    5. 釋放 TCP連接;
    6. 瀏覽器將該 html 文本渲染並顯示內容;  

HTTP特點:

  • 基於 請求-響應 的模式

    • HTTP協議規定,請求從客戶端發出,最后服務器端響應該請求並返回。換句話說,肯定是先從客戶端開始建立通信的服務器端在沒有接收到請求之前不會發送響應
  • 無狀態保存

    • 概念:

      • HTTP是一種不保存狀態,即無狀態(stateless)協議,即HTTP協議自身不對請求和響應之間的通信狀態進行保存。
      • 只要連接中斷,就撤銷當前所有信息,即每次開始時都是個完全空白的狀態
    • 目的:

      • 為了更快地處理大量事務,確保協議的可伸縮性,而特意把HTTP協議設計成如此簡單的。
    • 弊端:

      • 信息的不存儲,對於必須要存儲某些信息的網站來說,意味着:

      • 我輸入一個網頁並回車,一個套接字返回我要訪問的html,然后他就走了,然后當我要進行登陸操作時,又來了一個套接字接待我,給我返回登陸的網頁,然后他也走了。我在輸入完信息后回車進行登陸,又一個套接字過來拿着我的請求中的信息去數據庫里進行比對,檢驗完后,它就走了,臨走前返回我一個登陸成功,這時,如果我要進行基於用戶的操作時,一個新的套接字過來說,你還沒登陸啊,怎么能進行這個操作,我....
        
      • 基於上述情況,cookie由此誕生。

  • 無連接

    • 概念:
      • 無連接的含義是限制每次連接只處理一個請求。服務器處理完客戶的請求,並收到客戶的應答后,即斷開連接。
    • 目的:
      • 采用這種方式可以節省傳輸時間,並且可以提高並發性能,不能和每個用戶建立長久的連接,請求一次響應一次,服務端和客戶端就中斷了。
    • 優勢:
      • 適用於重瀏覽型網頁騰出線程來接待新用戶,防止占用套接字不發請求的用戶
  • 短連接:

    • 概念:

      • HTTP/1.1 版本之后,采用的是短連接的方式:即套接字響應完后,不會馬上關閉,而是等待幾秒鍾的時間(程序員可以自行設定),如果客戶端在這段時間內沒有響應的話,才會斷開。
    • 目的

      • 這樣做的主要目的還是為了節省時間,因為重新創建套接字也是需要時間的,目前默認3s左右。對於一個連續操作的客戶端來說,如果他在短時間內點擊了html中的很多選項,這樣每次服務器都需要創建一個套接字來接待他,僅創建套接字的時間就足以拖垮效率。
      • 而對於一個操作間隔很長的客戶端來說,無連接很明顯是個足夠優秀的選擇
    • 短連接等待時間

      • 網站根據自己網站用戶的行為來分析統計出一個最優的等待時間。
    • 優勢:

      • 適用於強操作性網頁,可以防止單個用戶短時間就占用多個套接字(因為無連接的方式,套接字響應完請求就自行關閉了,所以新的請求就要重新建立套接字)。
  • 因此,無連接、短連接沒有絕對的優劣,主要還是看客戶端需求。

HTTP請求方法

get 拿數據

post 發數據

報文格式

請求報文

響應報文

  • 通過GET方式提交數據時,請求數據(頁面提交的信息)會放在原路徑后,並與原路徑組成一個新的路徑部分,因此get方式提交時路徑部分不止有路徑,且后面的請求數據部分一定為空
    • 這種形式還會出現一個問題就是:
      • 客戶端第一次訪問服務器時,通常是以域名的形式訪問的,之后就通過點擊超鏈接或敲回車自動轉載網頁的形式訪問服務器的其他頁面。
      • 上述后者是以URL{域名(或ip)+路徑}的形式訪問服務器的,這就意味着,頁面在訪問服務器時,域名+路徑會直接顯示在瀏覽器網址欄,即用戶的請求數據會以明文形式顯示在網址欄,這對於用戶的個人數據等信息來說是不能接受的。
  • GET方式以?分割路徑和請求數據請求數據中的參數之間以&相連,如EditBook?name=test1&id=123456.(請求頭里面那個content-type做的這種參數形式,后面講) POST方法是把頁面提交的數據放在HTTP包的請求數據中
  • GET提交的數據大小有限制(因為瀏覽器對URL的長度有限制),而POST方法提交的數據沒有限制.
  • GET與POST請求在服務端獲取請求數據方式不同,就是我們自己在服務端取請求數據的時候的方式不同了,這句廢話昂。

HTTP狀態碼

  • 所有HTTP響應的第一行都是狀態行,依次是當前HTTP版本號,3位數字組成的狀態代碼,以及描述狀態的短語,彼此由空格分隔。比如"HTTP/1.1 200 OK"
  • 狀態代碼的第一個數字代表當前響應的類型:
    • 1xx消息——請求已被服務器接收,繼續處理
    • 2xx成功——請求已成功被服務器接收、理解、並接受(沒問題)
    • 3xx重定向——需要后續操作才能完成這一請求
    • 4xx請求錯誤——請求含有詞法錯誤或者無法被執行(客戶端請求出現問題)
    • 5xx服務器錯誤——服務器在處理某個正確請求時發生錯誤(服務器出現問題)

URL

超文本傳輸協議(HTTP)的統一資源定位符將從因特網獲取信息的五個基本元素包括在一個簡單的地址中(即一個完整的網頁):

  • 傳送協議(http/https(http基礎上進行加密,提升安全性))。
  • 層級URL標記符號(為[//],固定不變)
  • 訪問資源需要的憑證信息(可省略)
  • 服務器。(通常為域名,有時為IP地址)
  • 端口號。(以數字方式表示,若為HTTP的默認值“:80”可省略)
  • 路徑。(以“/”字符區別路徑中的每一個目錄名稱,第一個/前就是域名(或IP)
  • 查詢。(GET模式的窗體參數,以“?”字符為起點,每個參數以“&”隔開,再以“=”分開參數名稱與數據,通常以UTF8的URL編碼,避開字符沖突的問題)
  • 片段。以“#”字符為起點
以http://www.luffycity.com:80/news/index.html?id=250&page=1 為例, 

其中:
http,是協議;
www.luffycity.com,是服務器;
80,是服務器上的默認網絡端口號,默認不顯示;
/news/index.html,是路徑(URI:直接定位到對應的資源);
?id=250&page=1,是查詢。

大多數網頁瀏覽器不要求用戶輸入網頁中“http://”的部分,因為絕大多數網頁內容是超文本傳輸協議文件。同樣,“80”是超文本傳輸協議文件的常用端口號,因此一般也不必寫明。一般來說用戶只要鍵入統一資源定位符的一部分(www.luffycity.com:80/news/index.html?id=250&page=1)就可以了。

由於超文本傳輸協議允許服務器將瀏覽器重定向到另一個網頁地址,因此許多服務器允許用戶省略網頁地址中的部分,比如 www。從技術上來說這樣省略后的網頁地址實際上是一個不同的網頁地址,瀏覽器本身無法決定這個新地址是否通,服務器必須完成重定向的任務。

web框架

  • 瀏覽器對頁面進行渲染時,需要html文件中通過各種方式引用的所有素材以及網頁的圖標,並且這個過程是以異步的形式向服務器發送請求的(遇到第一個需要的素材,就給服務器發請求說我要,然后html中的代碼繼續往下走)
  • rb形式發送文件數據時,發送的只有文檔里的內容,文件的外殼跟名字都沒有被發送

函數版web框架

  • from threading import Thread
    import socket
    
    
    server = socket.socket()
    
    server.bind(('127.0.0.1',8001))
    server.listen()
    
    
    def html():
        with open('home.html', 'rb') as f:
            to_client_data = f.read()
        return to_client_data
    
    def css():
        with open('home.css', 'rb') as f:
            to_client_data = f.read()
        return to_client_data
    
    def js():
    
        with open('home.js', 'rb') as f:
            to_client_data = f.read()
        return to_client_data
    
    def jpg():
    
        with open('1.jpg', 'rb') as f:
            to_client_data = f.read()
        return to_client_data
    
    def ico():
        with open('xx1.ico', 'rb') as f:
            to_client_data = f.read()
        return to_client_data
    
    url_patterns = [
        ('/',html),
        ('/home.css',css),
        ('/home.js',js),
        ('/1.jpg',jpg),
        ('/favicon.ico',ico),
    ]
    
    while 1:
        conn,addr = server.accept()
        from_client_msg = conn.recv(1024).decode('utf-8')
    
        # print(from_client_msg)
        # print(from_client_msg.decode('utf-8'))
        request_path = from_client_msg.split(' ')[1]
      	# 拿到用戶的訪問路徑
        print(request_path)
        conn.send(b'HTTP/1.1 200 ok\r\n\r\n')
    
        for i in url_patterns:
            if i[0] == request_path:
    		# 進行信息比對,你要訪問的路徑在我的url-func關系中,就調用對應的函數給他返回對應頁面。
                to_client_data = i[1]()
    
    
        conn.send(to_client_data)
        conn.close()
    
    
    server.close()
    
    

並發版web框架

  • from threading import Thread
    import socket
    
    
    server = socket.socket()
    
    server.bind(('127.0.0.1',8001))
    server.listen()
    
    
    def html(conn):
        with open('home.html', 'rb') as f:
            to_client_data = f.read()
        conn.send(to_client_data)
        conn.close()
        # return to_client_data
    
    def css(conn):
        with open('home.css', 'rb') as f:
            to_client_data = f.read()
        conn.send(to_client_data)
        conn.close()
    
    def js(conn):
    
        with open('home.js', 'rb') as f:
            to_client_data = f.read()
        conn.send(to_client_data)
        conn.close()
    
    def jpg(conn):
    
        with open('1.jpg', 'rb') as f:
            to_client_data = f.read()
        conn.send(to_client_data)
        conn.close()
    
    def ico(conn):
        with open('xx1.ico', 'rb') as f:
            to_client_data = f.read()
        conn.send(to_client_data)
        conn.close()
    
    url_patterns = [
        ('/',html),
        ('/home.css',css),
        ('/home.js',js),
        ('/1.jpg',jpg),
        ('/favicon.ico',ico),
    ]
    
    while 1:
    
        conn,addr = server.accept()
        from_client_msg = conn.recv(1024).decode('utf-8')
    
        request_path = from_client_msg.split(' ')[1]
        print(request_path)
        conn.send(b'HTTP/1.1 200 ok\r\n\r\n')
    
        for i in url_patterns:
            if i[0] == request_path:
                target_thread = Thread(target=i[1],args=(conn,))
                # to_client_data = i[1]()
                target_thread.start()
        server.close()
    	
        # 注意:這里不能跟函數web框架一樣在循環外關閉套接字、服務器
        # 因為我的代碼里只有一個變量名。通俗點形容:當一個客戶來訪問服務器,我就創建一個線程給他個名字叫:conn,並讓她去服務這個客戶,他倆離開后,如果又來一個用戶,我就再創建一個線程,並且把之前那個線程的名字給拿走給這個新的線程,但是這樣並不影響之前的線程服務用戶,他倆玩他倆的。
        # 但當其中一個線程先運行完后,他就會執行循環外的conn.close(),這時如果正好創建了一個線程,把名字也給了,但是還沒來得及去服務,他就被辭職了,這時沒人服務用戶了,程序就出錯了!而且,在辭職完conn后,還要關門停止營業,這就不是我預期的效果了。
        
    

動態頁面版web框架

  • 動態頁面的意思是:同一個url,我每次打開時都不同於之前。而非,帶閃圖、動態等重復變化的頁面。

  • from threading import Thread
    import socket
    import time
    
    server = socket.socket()
    
    server.bind(('127.0.0.1',8001))
    server.listen()
    
    
    def html(conn):
        current_time = time.time()
        # import pymysql
    
        with open('home.html', 'r',encoding='utf-8') as f:
            to_client_data = f.read()
        to_client_data = to_client_data.replace('%xxoo%',str(current_time))
    
        conn.send(to_client_data.encode('utf-8'))
        conn.close()
        # return to_client_data
    
    def css(conn):
        with open('home.css', 'rb') as f:
            to_client_data = f.read()
        conn.send(to_client_data)
        conn.close()
    
    def js(conn):
    
        with open('home.js', 'rb') as f:
            to_client_data = f.read()
        conn.send(to_client_data)
        conn.close()
    
    def jpg(conn):
    
        with open('1.jpg', 'rb') as f:
            to_client_data = f.read()
        conn.send(to_client_data)
        conn.close()
    
    def ico(conn):
        with open('xx1.ico', 'rb') as f:
            to_client_data = f.read()
        conn.send(to_client_data)
        conn.close()
    
    url_patterns = [
        ('/',html),
        ('/home.css',css),
        ('/home.js',js),
        ('/1.jpg',jpg),
        ('/favicon.ico',ico),
    ]
    
    while 1:
    
        conn,addr = server.accept()
        from_client_msg = conn.recv(1024).decode('utf-8')
    
        request_path = from_client_msg.split(' ')[1]
        print(request_path)
        conn.send(b'HTTP/1.1 200 ok\r\n\r\n')
    
        for i in url_patterns:
            if i[0] == request_path:
                target_thread = Thread(target=i[1],args=(conn,))
                # to_client_data = i[1]()
                target_thread.start()
    
    server.close()
    

wsgiref版web框架

  • wsgiref模塊是對socket的封裝,其內部的environ是對http信息進行了切割,並整理成一個字典,想要用戶的什么數據,只要知道這個數據對應的鍵名就可以直接拿到了,而什么數據對應什么鍵都是其內部定義好了的,所以用起來很方便。

  • Django中也有可以實現wsgiref模塊功能的元素,也是通過某些功能直接將http信息做好了切割,保存,通過指定方式去拿指定信息就可以了。

  • from wsgiref.simple_server import make_server
    
    url_patterns = [('/index',index),]
    
    def index():
        with open('html', 'rb') as f:
            to_client_data = f.read()
        return to_client_data
    
    def application(environ, start_response):
        """
    
        :param environ:  封裝了所有的http協議相關信息--一個字典{'path_info':'/'}
        :param start_response:
        :return:
        """
    
        request_path = environ['PATH_INFO'] 
        # 通過固定鍵名'PATH_INFO'直接拿到用戶的請求路徑
        for i in url_patterns:
            if i[0] == request_path:
                ret = i[1]()
    
        start_response('200 OK', [('k1','v1'),])
        # print(environ)
        # print(environ['PATH_INFO'])
        return [ret]
    
    httpd = make_server('127.0.0.1', 8080, application)
    
    httpd.serve_forever()
    

B/S概念

  • 隨着Internet和WWW的流行,以往的主機/終端和C/S都無法滿足當前的全球網絡開放、互連、信息隨處可見和信息共享的新要求,於是就出現了B/S架構,即瀏覽器/服務器結構。它是C/S架構的一種改進,可以說屬於三層C/S架構。主要是利用了不斷成熟的WWW瀏覽器技術,用通用瀏覽器就實現了原來需要復雜專用軟件才能實現的強大功能,並節約了開發成本,是一種全新的軟件系統構造技術。

結構:

  • 第一層是瀏覽器,即客戶端,只有簡單的輸入輸出功能,處理極少部分的事務邏輯。由於客戶不需要安裝客戶端,只要有瀏覽器就能上網瀏覽,所以它面向的是大范圍的用戶,所以界面設計得比較簡單,通用。

  • 第二層是WEB服務器,扮演着信息傳送的角色。當用戶想要訪問數據庫時,就會首先向WEB服務器發送請求,WEB服務器統一請求后會向數據庫服務器發送訪問數據庫的請求,這個請求是以 SQL 語句實現的。

  • 第三層是數據庫服務器,他扮演着重要的角色,因為它存放着大量的數據。當數據庫服務器收到了WEB服務器的請求后,會對 SQL 語句進行處理,並將返回的結果發送給WEB服務器,接下來,WEB服務器將收到的數據結果轉換為HTML文本形式發送給瀏覽器,也就是我們打開瀏覽器看到的界面。

原理

  • B/S架構采取瀏覽器請求,服務器響應的工作模式。

  • 用戶可以通過瀏覽器去訪問Internet上由Web服務器產生的文本、數據、圖片、動畫、視頻點播和聲音等信息;

  • 而每一個Web服務器又可以通過各種方式與數據庫服務器連接,大量的數據實際存放在數據庫服務器中;

  • 從Web服務器上下載程序到本地來執行,在下載過程中若遇到與數據庫有關的指令,由Web服務器交給數據庫服務器來解釋執行,並返回給Web服務器,Web服務器又返回給用戶。在這種結構中,將許許多多的網連接到一塊,形成一個巨大的網,即全球網。而各個企業可以在此結構的基礎上建立自己的Internet。

  • 在 B/S 模式中,用戶是通過瀏覽器針對許多分布於網絡上的服務器進行請求訪問的,瀏覽器的請求通過服務器進行處理,並將處理結果以及相應的信息返回給瀏覽器,其他的數據加工、請求全部都是由Web Server完成的。通過該框架結構以及植入於操作系統內部的瀏覽器,該結構已經成為了當今軟件應用的主流結構模式。

B/S優缺點

  • B/S架構最大的優點是總體擁有成本低、維護方便、 分布性強、開發簡單,可以不用安裝任何專門的軟件就能 實現在任何地方進行操作,客戶端零維護,系統的擴展非常容易,只要有一台能上網的電腦就能使用。
  • 最大的缺點就是通信開銷大、系統和數據的安全性較難保障

C/S與B/S

  • 在響應速度,用戶界面,數據安全等方面,C/S強於B/S,但是在業務擴展和適用 www 條件下,B/S明顯勝過C/S。可以這么說,B/S的強項就是C/S的弱項,反之亦然。它們各有優缺點,相互無法取代。
  • C/S結構與B/S結構兩種模式各自擁有其特色優勢,在不同的系統環境與操作平台下,選擇較為接近或交叉進 行混合模式的使用,可以保證數據的敏感性、安全性和穩定發展,還可以加強對數據庫的修改與新增記錄的操作。 對客戶端程序進行保護,提高資源數據的交互性能,實現系統維護成本較低、維護方式較簡便、布局更合理、網絡數據使用效率較高的目的,采用C/S與B/S混合模式才是最佳方案。

C/S與B/S不同點

  • C/S B/S
    硬件環境 專用網絡 廣域網
    安全要求 面向相對固定的用戶群信息安全的控制能力強 面向不可知的用戶群對安全的控制能力相對較弱
    程序架構 更加注重流程系統運行速度可較少考慮 對安全以及訪問速度都要多重的考慮,是發展趨勢
    軟件重用
    系統維護 升級難 開銷小,方便升級
    處理問題 集中 分散
    用戶接口 與操作系統關系密切 跨平台,與瀏覽器相關
    信息流 交互性低 交互密集


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM