http協議無狀態中的【狀態】到底指的是什麼?!

先來看這句話的另外兩個概念:(標準的http協議是無狀態的,無連接的)

  1. 標準的http協議指的是不包括cookies, session,application(是手機應用)的http協議,他們都不屬於標準協議,雖然各種網絡應用提供商,實現語言、web容器等,都默認支持它
  2. 無連接指的是什麼
    1. 每一個訪問都是無連接,服務器挨個處理訪問隊列裏的訪問,處理完一個就關閉連接,這事兒就完了,然後處理下一個新的
    2. 無連接的含義是限制每次連接只處理一個請求。服務器處理完客戶的請求,並收到客戶的應答後,即斷開連接

 

對於【無狀態】,我看到很多隔着一層磨砂玻璃一樣的模糊說法(官方或者教程裏的說法),看着非常難受(但其實算是對的)(後來我發現我爲什麼覺得它看着難受了,因爲他們引入了很多新的,而且明顯是一個可能用在很多地方的廣義名詞,這些詞最大的作用就是,混淆概念,下面我標註了)

  1. 協議對於事務處理沒有記憶能力【事物處理】【記憶能力】
  2. 對同一個url請求沒有上下文關係【上下文關係】
  3. 每次的請求都是獨立的,它的執行情況和結果與前面的請求和之後的請求是無直接關係的,它不會受前面的請求應答情況直接影響,也不會直接影響後面的請求應答情況【無直接聯繫】【受直接影響】
  4. 服務器中沒有保存客戶端的狀態,客戶端必須每次帶上自己的狀態去請求服務器【狀態】

 

我必須得到確切而具體的解釋!

 

這幾點給了我下一步思考的方向:

  1. 【服務器中沒有保存客戶端的狀態,客戶端必須每次帶上自己的狀態去請求服務器 】這裏的客戶端的狀態是不是確切地指服務器沒有保存客戶的信息呢?但顯然不是啊
  2. 【HTTP無狀態的特性嚴重阻礙了這些應用程序的實現,畢竟交互是需要承前啓後的,簡單的購物車程序也要知道用戶到底在之前選擇了什麼商品】我對此質疑爲什麼無狀態就不能實現購物車呢?服務器就不能存儲東西了麼?
  3. 【 每次的請求都是獨立的,<它的執行情況和結果>與<前面的請求>和<之後的請求>是無直接關係的】我覺得這個說法比較靠譜,但是所謂的不同請求間的沒有關係,是指的請求內容沒有關係,還是隻是指請求本身沒有關係?
    1. 請求內容沒有關係只可能是服務器上不存有用戶數據纔可能啊,但是顯然是存有的啊
    2. 請求本身沒有關係,這又有什麼意義呢,每一次的請求有什麼價值?

 

根據這個方向我做了一個模擬訪問實驗:假如沒有cookie沒有session,只有http的時候,那當一個註冊用戶訪問這個購物網站的時候,會發生這些事情:

  1. 前提情況:
    1. 服務器肯定爲每個註冊用戶建立了數據表,記錄用戶的數據
    2. http是無連接的
  2. 第一步需要登錄
    1. 用戶通過http把用戶的用戶名和密碼發送給服務器,服務器把他們跟自己存有的用戶資料對比,如果一致,則返回信息登錄成功
  3. 然後用戶點擊某一商品頁
    1. 這個動作相當於輸入一個商品頁的網址
    2. 假如商品頁比較機密不對外公開,需要是用戶才能訪問
    3. 而雖然http能傳送用戶名和密碼,而且剛纔也輸入了,還驗證成功了,但是因爲服務器既不會記得你登錄的狀態,你的客戶端也不會存儲你剛纔輸入的用戶名和密碼
    4. 所以因爲這一次訪問因爲無法確定你的身份,只能訪問失敗
      1. 這時候如果要解決這個問題,而且沒有cookie沒有session,那就只能你在訪問網址的同時繼續帶上你的用戶名和密碼(繼續輸入咯)其實就像我現在的APP一樣
  4. 假設上一步的問題解決了,就是每次訪問的時候都會手動輸入用戶名和密碼,然後現在的情況是:你已經選了幾件商品在你的購物車中,你想再添加一件商品,於是你點擊某個商品旁邊的加號
    1. 這個動作也相當於輸入一個網址,網址的內容是發送一個請求,往你的購物車中加入這個商品
    2. 系統首先用你傳來的用戶名和密碼驗證你的身份,然後訪問你的數據庫,在其中的購物車屬性下加一條數據,就是這個商品的數據
    3. 操作結束後,返回操作成功,並結束訪問
  5. OK,實驗結束,看似沒有cookie沒有session也能湊合解決問題,其實兩個操作都有很大的問題
    1. 你每訪問一次需要權限的內容都需要在客戶端輸入用戶名和密碼,這一項的繁瑣就不必贅述了
    2. 你的每一次操作都要與系統底層的數據庫進行交互
      1. 多次少量的訪問存在非常大的性能浪費。非常容易就能想到肯定是一次大量的操作更加有效率,於是就想到了緩存區
    3. 你的非重要瑣碎數據也被寫進數據庫中,跟你的主要數據放在一起
      1. 一次次添加和刪除購物車其實只是跟你這次瀏覽,或者叫這次會話有關,是臨時的數據,跟用戶的主要信息無關,它們沒什麼價值,純粹的冗餘數據(不排除現在有的公司覺得這種數據也有非常大的價值可以讓它們巧妙的利用),用什麼存放這些臨時的數據,我們也很容易想到緩存區

 

經過這個模擬訪問實驗,結合前面的思考方向,我們知道了三點:

  1. 服務器上肯定存有用戶的數據,你提交的增刪改查它也能夠處理,所以這句話中【服務器中沒有保存客戶端的狀態】的狀態並不是指用戶的數據,我們的猜測不對
  2. 我們的質疑對了,無狀態能實現購物車,可以通過服務器上存有的用戶數據來實現
  3. 但是,使用上面這種方式實現購物車,存在三個比較大的問題。由此,我們不禁會想,這三個問題的解決是不是跟我們不確切瞭解的【狀態】一詞有關?於是,接下來我們來通過解決這三個問題來把【狀態】的意義探尋下去

 

由上所述,我們可以在http的基礎上增加一些機制來解決上面出現的三個問題

  1. 在用戶端增加一個記錄本是非常有必要的,正好官方加入的cookie機制跟這個一樣,它的用處也確實是上面討論的那樣,一般就是用來標識訪問者的身份
  2. 在服務器增加一個緩存區能同時解決後兩個問題
    1. 有了這個緩存區作爲一個數據緩衝,就不用一次次地訪問數據庫,浪費大量計算機資源,而是在最後統一歸入數據庫
    2. 有了這個緩存區,你就不用把臨時的數據放到數據庫中了,只需要在你們交流告一段落之後,再把數據整理,把有用的數據歸入數據庫
  3. 這裏就自然引申出了一個重要的概念:會話,它作爲一個緩衝存儲區被從數據庫中分離出來,理由並不生硬,它有其獨特的重要且不可替代的作用。這個東西恰好跟官方加入的session機制一樣
    1. 另外說一個非常具有迷惑性的容易讓人對session的主要作用產生偏離的理解:認爲session存在的價值就是給訪問者分配一個sessionID代替用戶名和密碼,
    2. 爲什麼非常具有迷惑性,因爲session確實做了這件事,而且也起到了很大的作用,所以它是對的,但是隻對一半,而且沒有涉及問題的本質,這種情況是最危險的(看似很有說服力,把你說服了,所以你很難有動力繼續找下去,但是真實情況跟它有偏差,但是偏差不大,所以又很難把你說服回來,只有隱隱的不對勁,這個時候你離真實最近,也離真實最遠)
    3. 那就順便說說它爲什麼是對的,也就是用session做的另一件有用的事:
      1. 給每個session一個ID,一方面用來方便自己查詢,另一方面把這個ID給用戶,用戶下一次訪問的時候就可以不用用戶名和密碼,而是直接使用這個ID來表明自己的身份
      2. 首先,這個ID安全嗎?這個ID比直接傳用戶名和密碼安全嗎?
        1. 你很容易會想到,本來用戶名和密碼的組合還特地設置地比較複雜,你這換一組數字就代替了,是不是太不安全了?
        2. 我們知道http協議本身是完全不加密的,如果使用用戶名和密碼,第一次訪問是放在http頭中,後邊自動保存了密碼就會放在cookie中,這些都完全沒有加密,它的安全性基本爲0,就是裸奔了,只要被竊取,那就丟失了
        3. 所以,就這個意義來講,sessionID的安全性跟使用用戶名和密碼沒什麼區別
        4. 但是其實,雖然http本身不能加密,但是有些軟件什麼的,能在應用層面手動給你加密,比如QQ就會使用戶名密碼加臨時驗證碼聯合哈希,sessionID加一個時間戳簡單加密也是非常常用的方法
        5. 而且因爲sessionID本身有有效期,即使丟了,也可能很快失效,造成的損失可能沒那麼大,而用戶名跟密碼丟了,那就大了
        6. 所以總結就是:
          1. 不嚴格加密的sessionID和用戶名和密碼一樣,都不太安全
          2. 但是相比較來說,sessionID要安全一些
          3. 而使用https是完全安全的
      3. 然後,使用sessionID有哪些好處
        1. 方便直接根據ID查詢用戶對應的session
        2. 加密的時候計算量小
        3. 安全性不會降低,甚至還更高一些

 

OK,通過獨立地解決純http機制會產生的問題,我們探討了cookie和session機制的本質。而且想到:【使用http協議,服務器中不會保存客戶端的狀態】所產生的問題通過增加cookie和session機制解決了,是不是就意味着這個【狀態】跟cookie和session的關係非常緊密?所以這個無狀態指的是【沒有對 本次會話 設置一個緩存區,記錄這次會話的狀態,緩存區包括服務器端和用戶端】但好像還是沒有點破關鍵(主要是覺得跟前面那些官方對狀態的說法不太吻合,甚至沒有對應關係)

 

忽然我想到一個問題:一個有狀態的http是什麼樣的?

  1. 很難直接想象有狀態的http是什麼樣,因爲http這種機制是天然無狀態的
  2. 那就類比一下吧,另一個天然有狀態的機制叫TCP
    1. 如果有狀態的意思是它的每次請求是有聯繫的,那麼有狀態的TCP的樣子是:假如一份數據分了三份TCP包發送,那這個包上面會標明這是第幾個包,會標明這個包跟那幾個包是有聯繫的,有什麼聯繫
  3. 但好像這個有狀態的TCP跟我們想要的有狀態的HTTP沒有關係,因爲即使每次http請求之間互相有聯繫,它也不能解決上面提到的http無狀態的問題
  4. 誒,等等,好像能類比:
    1. 假如每個http連接都有一個簽名,於是第一次登陸成功之後,服務器就知道了這個簽名是允許登陸的,於是之後所有同樣簽名的http連接都能登陸,這裏利用了同一個用戶發出的http連接之間的同主人關係,這裏解決了一個保持登錄狀態的問題
    2. 同樣,來嘗試利用這個【每次http請求之間互相有聯繫】來解決上面碰到的那個問題【每一次操作都要與系統底層的數據庫進行交互】,但想了半天確實無法進行下去
    3. 不過我靈機一動,從另一個角度來想,好像解決了這個問題:
      1. 只有【每次http請求之間互相有聯繫】這個條件,無法解決【每一次操作都要與系統底層的數據庫進行交互】
      2. 因爲很明顯,要解決【每一次操作都要與系統底層的數據庫進行交互】就必須在服務器端開闢一塊緩存區
      3. 不過如果你思考一下如何實現【每次http請求之間互相有聯繫】,你就會發現,它也需要在服務器端開闢一塊緩存區
      4. 所以【在服務器端開闢一塊緩存區】纔是真正的條件,也就是說,它確實等價於【有狀態】
      5. 而且我也找到了這個【在服務器端開闢一塊緩存區】的條件跟前面那些官方對狀態的說法對應的點,那就是:
        1. 通過在服務器端開闢一塊緩存區,存儲、記憶、共享一些臨時數據,你就可以:
          1. 協議對於事務處理有記憶能力【事物處理】【記憶能力】
          2. 對同一個url請求有上下文關係【上下文關係】
          3. 每次的請求都是不獨立的,它的執行情況和結果與前面的請求和之後的請求是直接關係的【不獨立】【直接關係】
          4. 服務器中保存客戶端的狀態【狀態】
      6. 所以,這個狀態,加上前面說的客戶端也有cookie,就是指,客戶端和服務器在臨時會話中產生的數據!而前面也說道了,使用緩存區保存臨時會話中的數據是多麼重要
        1. 所以狀態不僅包括不同URL訪問之間的關係,還有對其他URL訪問的數據記錄,還有一些其他的東西,所以更確切地說,狀態應該是【實現了這些東西所憑藉的後面的緩存空間】中的客戶的臨時數據
        2. cookie和session應該是完全實現了有狀態這個功能

 

一種常見的對狀態的誤解:

  1. 有人在解釋HTTP的無狀態時,把它跟有連接對立,說是兩種方式,也就是如果想不無狀態,就必須有連接,但其實不然
  2. 有連接和無連接以及之後的Keep-Alive都是指TCP連接
  3. 有狀態和無狀態可以指TCP也可以指HTTP
  4. TCP一直有狀態,HTTP一直無狀態,但是應用爲了有狀態,就給HTTP加了cookie和session機制,讓使用http的應用也能有狀態,但http還是無狀態

開始TCP是有連接,後來TCP無連接,再後來也就是現在TCP是Keep-Alive,有點像有連接
參考:https://www.cnblogs.com/bellkosmos/p/5237146.html

 

對Http協議無狀態的理解

Http是一個無狀態協議,同一個會話的連續兩個請求互相不瞭解,他們由最新實例化的環境進行解析,除了應用本身可能已經存儲在全局對象中的所有信息外,該環境不保存與會話有關的任何信息。

自己的理解,在asp.net裏:每次提交服務器的頁面沒有任何關係,每次記錄在頁面的信息下次提交是記不住的,(除了應用本身可能已經存儲在全局對象中的所有信息外)在.net裏實際就是ViewState,ViewState是asp.net中保存頁面信息的基本單位,應用時就是保存在控件隱藏域等中的數據

協議的狀態是指下一次傳輸可以“記住”這次傳輸信息的能力.
http是不會爲了下一次連接而維護這次連接所傳輸的信息的.

無狀態是指,當瀏覽器發送請求給服務器的時候,服務器響應,但是同一個瀏覽器再發送請求給服務器的時候,他會響應,但是他不知道你就是剛纔那個瀏覽器,簡單地說,就是服務器不會去記得你,所以是無狀態協議。
而DNS是有狀態協議 。

HTTP是一個屬於應用層的面向對象的協議,HTTP協議一共有五大特點,1、支持客戶/服務器模式;2、簡單快速;3、靈活;4、無連接;5、無狀態;“無狀態”是HTTP協議的主要特點之一,以下爲“無狀態”的解釋。 無狀態:是指

協議對於事務處理沒有記憶能力。缺少狀態意味着如果後續處理需要前面的信息,則它必須重傳,這樣可能導致每次連接傳送的數據量增大。另一方面,在服務器不需要先前信息時它的應答就較快。

HTTP是Hyper Text Transfer Protocol的縮寫,顧名思義,這個協議支持着超文本的傳輸。那麼什麼是超文本呢?說白了就是使用HTML編寫的頁面。通常,我們使用客戶端瀏覽器訪問服務器的資源,最常見的URL也是以html爲後綴的文件。因此,我們可以說超文本是網絡上最主要的資源。

既然HTTP協議的目的在於支持超文本的傳輸,更加廣義一些就是支持資源的傳輸,那麼在客戶端瀏覽器向HTTP服務器發送請求,繼而HTTP服務器將相應的資源發回給客戶端這樣一個過程中,無論對於客戶端還是服務器,都沒有必要記錄這個過程,因爲每一次請求和響應都是相對獨立的,就好像你在自動售貨機前投下硬幣購買商品一樣,誰都不會也不需要記住這樣一個交易過程。一般而言,一個URL對應着唯一的超文本,而HTTP服務器也絕對公平公正,不管你是Michael,還是Jordon,它都會根據接收到的URL請求返回相同的超文本。正是因爲這樣的唯一性,使得記錄用戶的行爲狀態變得毫無意義,所以,HTTP協議被設計爲無狀態的連接協議符合它本身的需求。

然而,隨着時間的推移,人們發現靜態的HTML着實無聊而乏味,增加動態生成的內容纔會令Web應用程序變得更加有用。於是乎,HTML的語法在不斷膨脹,其中最重要的是增加了表單(Form);客戶端也增加了諸如腳本處理、DOM處理等功能;對於服務器,則相應的出現了CGI(Common Gateway Interface)以處理包含表單提交在內的動態請求。在這種客戶端與服務器進行動態交互的Web應用程序出現之後,HTTP無狀態的特性嚴重阻礙了這些應用程序的實現,畢竟交互是需要承前啓後的,簡單的購物車程序也要知道用戶到底在之前選擇了什麼商品。於是,兩種用於保持HTTP連接狀態的技術就應運而生了,一個是Cookie,而另一個則是Session。

Cookie是通過客戶端保持狀態的解決方案。從定義上來說,Cookie就是由服務器發給客戶端的特殊信息,而這些信息以文本文件的方式存放在客戶端,然後客戶端每次向服務器發送請求的時候都會帶上這些特殊的信息。讓我們說得更具體一些:當用戶使用瀏覽器訪問一個支持Cookie的網站的時候,用戶會提供包括用戶名在內的個人信息並且提交至服務器;接着,服務器在向客戶端回傳相應的超文本的同時也會發回這些個人信息,當然這些信息並不是存放在HTTP響應體(Response Body)中的,而是存放於HTTP響應頭(Response Header);當客戶端瀏覽器接收到來自服務器的響應之後,瀏覽器會將這些信息存放在一個統一的位置,對於Windows操作系統而言,我們可以從:[系統盤]:\Documents and Settings\[用戶名]\Cookies目錄中找到存儲的Cookie;自此,客戶端再向服務器發送請求的時候,都會把相應的Cookie再次發回至服務器。而這次,Cookie信息則存放在HTTP請求頭(Request Header)了。
有了Cookie這樣的技術實現,服務器在接收到來自客戶端瀏覽器的請求之後,就能夠通過分析存放於請求頭的Cookie得到客戶端特有的信息,從而動態生成與該客戶端相對應的內容。通常,我們可以從很多網站的登錄界面中看到“請記住我”這樣的選項,如果你勾選了它之後再登錄,那麼在下一次訪問該網站的時候就不需要進行重複而繁瑣的登錄動作了,而這個功能就是通過Cookie實現的。

與Cookie相對的一個解決方案是Session,它是通過服務器來保持狀態的。由於Session這個詞彙包含的語義很多,因此需要在這裏明確一下Session的含義。首先,我們通常都會把Session翻譯成會話,因此我們可以把客戶端瀏覽器與服務器之間一系列交互的動作稱爲一個Session。從這個語義出發,我們會提到Session持續的時間,會提到在Session過程中進行了什麼操作等等;其次,Session指的是服務器端爲客戶端所開闢的存儲空間,在其中保存的信息就是用於保持狀態。從這個語義出發,我們則會提到往Session中存放什麼內容,如何根據鍵值從Session中獲取匹配的內容等。
要使用Session,第一步當然是創建Session了。那麼Session在何時創建呢?當然還是在服務器端程序運行的過程中創建的,不同語言實現的應用程序有不同創建Session的方法,而在Java中是通過調用HttpServletRequest的getSession方法(使用true作爲參數)創建的。在創建了Session的同時,服務器會爲該Session生成唯一的Session id,而這個Session id在隨後的請求中會被用來重新獲得已經創建的Session;在Session被創建之後,就可以調用Session相關的方法往Session中增加內容了,而這些內容只會保存在服務器中,發到客戶端的只有Session id;當客戶端再次發送請求的時候,會將這個Session id帶上,服務器接受到請求之後就會依據Session id找到相應的Session,從而再次使用之。正式這樣一個過程,用戶的狀態也就得以保持了。有關Session的內容還比較多,在以後的Post中,我還將繼續講述。

綜上所述,HTTP本身是一個無狀態的連接協議,爲了支持客戶端與服務器之間的交互,我們就需要通過不同的技術爲交互存儲狀態,而這些不同的技術就是Cookie和Session了
參考:https://www.cnblogs.com/le-joke/p/5340201.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章