http爲何爲無狀態協議

http無狀態還是web應用無狀態

我們通常說的web應用程序的無狀態性的含義是什麼呢?

直觀的說,“每次的請求都是獨立的,它的執行情況和結果與前面的請求和之後的請求是無直接關係的,它不會受前面的請求應答情況直接影響,也不會直接影響後面的請求應答情況

要明白,這句話的含義是指在說明,http協議作爲技術背景的web應用程序請求——應答模式是無狀態的,這個事實基本不會發生改變,也不會因爲加入cookiessession機制而變成有狀態的。要明白,這種前後因果關係:“我們要實現的是一種web應用,實現這種應用的協議我們選擇了http這種本質上是無狀態的通信協議。但是事實上,我們需要我們的web應用是有狀態的。所以我們加入了cookiessession等機制去實現由狀態的web應用”。所以我們可以這麼理解:

Web應用=http協議+sessioncookies等狀態機制+其他輔助的機制。

其實,應用程序(軟件通信)的狀態與否是一個非常通用的概念。我們可知,在網絡協議中,我們稱TCP爲一個有狀態的傳輸層通信協議,而UDP則不是;IP是無狀態的。要明白這種狀態與否的判定,是面向你這一層次所指實現的功能——是否由上下文決定——來判定的(是否受之前的通信過程直接影響、是否直接影響之後的通信過程)

http協議無狀態是什麼意思?讓web應用有狀態的機制?

IP層以下的我們就不思考了。我們做一個網絡應用,需要使用網絡協議。其實按照原理上講,標準的TCP/IP協議提供給我們的網絡層協議(FTP, HTTP)不能直接的被稱爲應用,因爲在實現某種可用的、直接面向用戶的應用的時候(如web應用,人們可以上網),只有http協議還是不夠的。所以我們可以這麼理解。網絡標準協議分層中提供給我們的應用層協議,它更像是一種分類。自然界的應用可能是無窮盡的種類,但是根據他們的特點、傳輸的特色,標準的網絡協議在傳輸層(通用網絡協議)的基礎上封裝出若干種面向不同種類網絡應用的協議。

某種角度上講,我們想要實現某種可用的網絡應用,直接使用網絡協議的傳輸層給我們提供的接口就可以了(也就是socket接口),但是有時候,這種方式是有些麻煩的,所以我們還是根據你要實現的web應用,在已有的標準協議中提供的面向應用分類的協議中進行選擇。這樣可以免去那些繁瑣的、通用的工作。

http協議無狀態是什麼意思?讓web應用有狀態的機制?

可以看到,我們實際生活中的有關網絡的應用程序,與標準的網絡通信協議提供給我們的應用層協議是沒有絕對的對應關係。所以標準的網絡通信協議給我們提供的應用層協議,只是提供給我的一種“建議的”分類。建議你:“如果你要實現這樣的應用,你可以直接使用這個封裝協議,而不是socket接口”。

我們再看看,前面一副圖中,所給我們的關於網絡應用層次中的各層次的有無狀態情況。可以知道,支持協議(下層)的有無狀態,消費協議(上層)的有無狀態,沒有直接的關係。還是那句話,每層協議的有無狀態關係到它的本身功能執行的時候的有無狀態地特點。

1IP是無狀態的,它只負責將一個IP包發送到指定的IP地址上去。它不會考慮這個包與前面已經發送的包和後面的包的聯繫。(可能是重發包、可能是不連續包,它不管)。

(2)TCP是有狀態,它通過包頭中的一些控制字段(序列編碼等)來表明各個包之間的關係(前後關係,重包與否等等)。所以,通過這個協議你可以做到一個可靠的傳輸。那麼TCP面向連接的協議是什麼意思呢?其實這裏的面向連接其實就是“三次握手”。三次握手,首先可以保證對方的存在,其次握手的所交換的內容是爲將來進行有狀態的傳輸做準備。

(3) UDP是無狀態的,它僅僅是在IP上加了Port,其他的事情什麼也不幹。這樣它不可能做到可靠的傳輸,同樣也不需要連接。

(4) HTTP是無狀態的,它的底層協議是由狀態的TCP,但是HTTP的一次完整協議動作,裏面是使用有狀態的TCP協議來完成的。而每次協議動作之間沒有任何關係。例如:第7次請求HTTP協議包,並不知道,這個包是爲了什麼?它或許是因爲上次沒有請求成功而重傳,或許是上次的後續請求,或許是其他的,這些HTTP自身都不知道。

(5) www應用,但是很多時候,www應用是需要HTTP動作之間是有關聯的,那就是使應用有狀態。這樣才能提供給用戶最好的用戶體驗。

於是,問題就來了,爲什麼當初HTTP會設計成無狀態的,既然現在我們所需要的www應用是有狀態的,爲什麼給他提供的這樣的底層協議是無狀態的。我想這個問題,可以從歷史的角度去思考。在www應用還很簡單的時候,這個應用只是被用來瀏覽內容。如果只是瀏覽內容的話,無狀態的協議已經夠了,這樣實現可以減輕實現的負擔,因爲有狀態的協議實現起來代價相對來說是很高的(要維護狀態,根據狀態來處理情況,這就是爲什麼建議你可以不用session的時候就不用,因爲服務器要給你負擔起很多的東西,例如內存空間啊)。好,現在看來,似乎www 應用是大部分需要狀態了,那麼是否我們就應該改變這個協議來讓他變成一個有狀態的協議呢?從這個角度上講,我認爲是不應該的。

首先,web應用與文件傳輸是不同的,文件傳輸,從開始到結束是一個“儘可能做完”的動作,所以這類動作不會在資源佔有上,浪費它不該浪費的東西。而web應用中,用戶可能訪問一個頁面後,在那個頁面上逗留很久才跳轉到另外一個頁面,如果你需要我們在這兩個頁面(兩個http請求應答)之間維持狀態,是非常代價高的。

其次,歷史讓http無狀態,而應用需求對http提出有狀態的要求,按照軟件領域的通常做法是,保持歷史遺留的經驗(不再http協議本質上作太大的改動),兼容過去的軟件。在http上再加上一層來實現我們的目的( “再加上一層,你能做任何事”)。這一層,就是cookies,就是session等。

最後總結,http協議仍然保持無狀態,其充分的理由,並且,想要基於http協議的web應用變得有狀態,實現起來並不麻煩。

web應用都有哪些方法來讓應用有狀態

於是就引出了,在http協議的基礎上,web應用引入cookies, session, application。這樣的東西來保持web應用之間的狀態。

可知,cookies, sessionapplication都不是標準協議,但是各種網絡應用提供商,實現語言、web容器等,都默認支持它。當然這種支持與對網絡標準協議的支持是不同的,標準協議規定的接口,而這種機制,只是規定了思想。就告訴你,大的概念上,jspASPsession機制所要實現的功能和實現的方法不會有太大的出入。

有人將web應用中有無狀態的情況,比着顧客逛商店的情景。

顧客:瀏覽器訪問方;

商店:web服務器;

一次購買:一次http訪問

我們知道,上一次顧客購買,並不代表顧客下一個小時一定會買(當然也不能代表不會)。也就是說同一個顧客的不同購買之間的關係是不定的。所以說實在的,這種情況下,讓商店保存所有的顧客購買的信息,等到下一次購買可以知道這個顧客以前購買的內容代價非常大的。所以商店爲了避免這個代價,索性就認爲每次的購買都是一次獨立的新的購買。淺臺詞:商店不區分對待老顧客和新過客。這就是無狀態的。

但是,商店爲了提高收益。她是想鼓勵顧客購買的。所以告訴你,只要你在一個月內購買了5瓶以上的啤酒,就送你一個酒杯。

我們看看這種情況我們怎麼去實現呢?

A,給顧客發放一個磁卡,裏面放有顧客過去的購買信息。

這樣商店就可以知道了。這就是cookie.

B,給顧客發放一個唯一號碼,號碼制定的顧客的消費信息,存儲在商店的服務器中。這就是session

最後,商店可以全局的決定,是5瓶爲送酒杯還是6瓶。這就是application

其實,這些機制都是在無狀態的傳統購買過程中加入了一點東西,使整個過程變得有狀態。Web應用就是這樣的。

注意,viewstate

其實從我們上面的分析看來,application不應該被視爲這種意義上出現的維護狀態的機制。它是決定怎麼應用程序的“配製文件”。但是如果你從這種狀態維持機制所覆蓋的範圍來推導,你會發現,application好像也算得上。

Session所控制的範圍是一個session。一個會話,會話從第一次訪問服務器開始存在,到服務器調用session.invalidator()(可能是超時,可能是其它原因)。

Cookies所控制的範圍有它自己的定義(session沒有直接的關係),可以長可以短。只要服務器放在用戶文件系統中的cookies沒有被刪除,至少服務器還識別它。它的控制範圍就是還在的。

這個角度上講,SessionCookies都可以歸爲跨頁面的狀態。但是session跨不出一次會話,Cookies跨不出兩端的限制。

Application,則是關聯這個網絡應用程序的。

除了這三種狀態機制,有些網絡應用的特別實現還各自特殊的東西。像ASP.netviewstate。這個東西,其實就是使用input type=”hyde”的東西來實現的。再加上web服務器那邊輔助,就可以實現,一個頁面在“回傳”的時候還能保持上一次的頁面狀態。

其實,這裏要說明的就是“回傳”的意思,事實上,無狀態的http協議下,是沒有所謂的回傳的概念的。這裏的回傳,情景可以這麼理解。

我在客戶端填寫一定的數據(在文本框中、密碼框中、下拉列表中)。然後觸發一個訪問服務器的動作,例如:提交。這個時候服務器接受到我的請求然後又返回剛纔這個頁面給我們。這種情景我們很常見(輸入用戶名密碼,點擊“登陸”,服務器端判斷密碼不對,就返回登陸頁面,但是之前我們填寫的內容並沒有被擦出。)這種情景就好像實現了一種回傳(你傳給我,我傳還給你)。當然,如果你瞭解web服務的工作模式,這種回傳只會是一種假象。前後兩個頁面根本不是一個頁面。其實我們可以實現這種情景(不考慮Ajax)。頁面上的數據全部通過request的方式傳到服務器,服務器返回頁面的時候,將數據由注入到頁面中。

viewstate就可以讓用戶很容易的實現這種功能。但是它有一個問題就是它附屬於頁面上的hide控件。雖然前後是兩個不同的頁面,但是來自一個ASPX模板,頁面上的狀態數據就在這些同模板頁面的hide空間之間進行傳播(由服務器控制),不可能,也不應該傳遞到別的ASP.new的頁面上去。所以我們稱他爲頁面級的狀態維持機制。

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