由ASP.NET所謂前臺呼叫後臺、後臺呼叫前臺想到HTTP——理論篇

謙行發表於2013-09-20

工作兩年多了,我會經常嘗試給公司小夥伴兒們解決一些問題,幾個月下來我發現初入公司的小朋友最愛問的問題就三個

1. 我想前臺呼叫後臺的XXX方法怎麼弄啊?

2. 我想後臺呼叫前臺的XXX JavaScript方法怎麼弄啊?

3. 怎麼用JavaScript找到/建立/修改XXX這個伺服器端控制元件啊?

每次我會跟小朋友分析一下為什麼會有如此荒誕不經的想法,然後說原來你做XXX啊,那你應該這樣,可發現這種模式太失敗了,因為隔幾天我又會聽到小朋友還是有類似的疑惑。

我決定以後再有誰問這個問題,我就讓誰給我講講HTTP協議,幾次過後效果非凡啊,看看這兩個問題和HTTP協議有什麼關係吧

HTTP協議

HTTP協議即超文字傳輸協議 (HTTP-Hypertext transfer protocol) 是分散式,協作式,超媒體系統應用之間的通訊協議。是全球資訊網(world wide web)交換資訊的基礎。是一種詳細規定了瀏覽器和全球資訊網伺服器之間互相通訊的規則,通過因特網傳送全球資訊網文件的資料傳送協議。

這是從百度上抄來的定義,感覺味同嚼蠟,反正我要是問人什麼是HTTP,要是這麼回答我,我肯定得急,所以還有

HTTP協議允許將超文字標記語言 (HTML) 文件從 Web 伺服器傳送到 Web 瀏覽器。HTML 是一種用於建立文件的標記語言,這些文件包含到相關資訊的連結。您可以單擊一個連結來訪問其它文件、影象或多媒體物件,並獲得關於連結項的附加資訊。

還是不明白,看看HTTP的請求-響應模型就清楚了

HTTP協議規定的互動很簡單,客戶端向伺服器傳送包含著資訊的請求(絕逼不是整個HTML頁面),伺服器接到請求後,根據請求資訊生成響應(什麼響應都可能,多數是HTML頁面文字),然後把響應發給瀏覽器(如果響應是HTML頁面的話,瀏覽器就載入這個新頁面了)

image

HTTP的請求-響應模型非常簡單,可是初入門的時候我們會誤會它很深

瀏覽器到底向伺服器請求什麼了

請求不是整個HTML頁面,小朋友們在ASP.NET的codeBehind中經常試圖去Request物件中找頁面的某個DIV,認為請求就是整個HTML頁面,理由也很充分,我能夠找到伺服器端控制元件,怎麼就找不到HTML控制元件呢。訪問百度首頁一下看看瀏覽器究竟請求了什麼

當我們在瀏覽器位址列輸入uri回車或者頁面form提交,瀏覽器會把請求打成包,HTTP請求包(GET/POST等請求方法)由三個部分構成,

<request-line>
<headers>
<blank line>
[<request-body>]

request-line:俗稱請求行,類似於這樣 Get / HTTP /1.0,用來說明請求型別、要訪問的資源路徑(/ 表示跟路徑)以及使用的HTTP版本。

headers: 也就是我們常說的HTTP Headers,訪問百度首頁的時候是一個這樣的東東

image

需要注意的是heasers中包括了該域下的cookie

blank line:這就是一個空行,還是必須的

request-body:這個在post請求時有用,是頁面表單元素的name和value,也就是在Resquest.Forms中能取到的內容,在百度上搜尋得到,request body是這樣的

image

是的,HTTP 請求包中就這些內容,沒有什麼div啊,什麼伺服器端控制元件啊什麼的了

為什麼能在codeBehind中操作伺服器端控制元件,頁面上卻不能用JavaScript來做

簡單的說伺服器端控制元件是伺服器的,伺服器並沒有把這個給客戶端,給客戶端的只是伺服器端控制元件render的html文字,所以伺服器端找到伺服器端控制元件(你看人家都叫伺服器端控制元件了),客戶端找不到。看起來很高階深奧,實際很簡單,看看伺服器交給瀏覽器的是什麼,和Request格式類似,Response格式如下

<status-line>
<headers>
<blank line>
[<response-body>]

status-line:表示請求的狀態碼,也就是我們常見的200、301、404、500神馬的

headers:一些響應的資料,還是上面例子,在百度上搜尋得到,response headers是這樣的

image

content-type是不是很熟悉?值得注意的是response headers中同樣包含cookie

blank-line:仍舊是不可或缺的空白行

response-body:響應內容,訪問百度首頁response body 大概這樣,其實也就是百度首頁的HTML程式碼

image

也就是說,也就是說response body在一般情況下就是得到的就請求頁面的HTML,瀏覽器接收到response後會按照response body重新載入渲染頁面內容。寫過Web Control的同學肯定知道,伺服器端控制元件render成什麼了

看一個最簡單的頁面

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="FrontBehind.Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Button ID="btnServer" runat="server" Text="Server" OnClick="btnServer_Click" />
    </div>
    </form>
</body>
</html>

頁面上只有一個伺服器端的控制元件(不要太計較),看看生成的頁面內容

image

伺服器端的控制元件Button經過處理後交給客戶端時已經變成了一個 submit型別的input,頁面上通過JavaScript當然找不到這個伺服器端控制元件了,有興趣同學可以看看Web Control的render control方法,所有的Web Control在Page render的時候都會呼叫此方法,將伺服器端控制元件按照自己規則render成瀏覽器認識的HTML,然後放到Resoponse中。

瀏覽器從噢乖伺服器得到的是全新的HTML文字(不考慮Ajax),沒有其它伺服器控制元件神馬的。

在編碼的時候的頁面和瀏覽器拿到的頁面有什麼關係

可能偶同學會對上面的理論有疑問,我們在程式設計的時候寫的頁面,上面有很多伺服器端控制元件,和最終瀏覽器展示的頁面有什麼關係?!這就需要我們講講動態網頁的前世今生。

最開始的時候頁面全都是靜態的HTML文字,瀏覽器做的事情就是告訴伺服器我要哪個頁面,伺服器傳給你這個頁面,就像張三家開了個磚窯,你需要了就會吼一嗓子,張三,給我塊磚!然後張三扔給你。

但是這樣好單調,有時候頁面內容相當有規律,但是頁面是靜態的就得準被很多頁面,也沒法做到和使用者互動,於是產生了ASP等伺服器指令碼語言,可以根據使用者引數或者預設條件來修改頁面部分內容,不再簡單返回瀏覽器靜態頁面檔案內容,而是根據規則生成HTML文字,然後返回給瀏覽器。

後來物件導向的普及及模組兒化程式設計等等思想的影響,有一些常用的規則,比如畫出個日曆啊我們可以寫成一個單獨的模組兒,然後通過指令使其嵌在頁面內,用的時候寫一條指令就可以了,這就是ASP.NET 中例如Button等的Web Control,也就是伺服器端控制元件。

如果伺服器判斷出瀏覽器請求的是帶有伺服器指令碼的頁面的時候(一般根據擴充名或者Map關係判斷),就會交給固定型別指令碼的“直譯器”去處理這些指令碼,轉換成HTML語句,然後返回給客戶端。

所以瀏覽器呈現的頁面是我們根據開發時候定義的規則,動態生成的HTML文字載入渲染的結果

HTTP工作流程

  1. 一次HTTP操作稱為一個事務,其工作過程可分為四步:
    首先客戶機與伺服器需要建立連線。只要單擊某個超級連結,HTTP的工作開始。
    建立連線後,客戶機傳送一個請求給伺服器,請求方式的格式為:統一資源識別符號(URL)、協議版本號,後邊是MIME資訊包括請求修飾符、客戶機資訊和可能的內容。
    伺服器接到請求後,給予相應的響應資訊,其格式為一個狀態行,包括資訊的協議版本號、一個成功或錯誤的程式碼,後邊是MIME資訊包括伺服器資訊、實體資訊和可能的內容。
    客戶端接收伺服器所返回的資訊通過瀏覽器顯示在使用者的螢幕上,然後客戶機與伺服器斷開連線。

HTTP特點

通過上面的說明可以看出HTTP協議有幾個特徵

1.HTTP協議永遠都是客戶端發起請求,伺服器回送響應。這樣就限制了使用HTTP協議,無法實現在客戶端沒有發起請求的時候,伺服器將訊息推送給客戶端。必須是客戶端給伺服器要,而不能伺服器主動給客戶端。

2.HTTP協議是一個無狀態的協議,同一個客戶端的這次請求和上次請求是沒有對應關係。也就是說你連續兩次訪問百度,這兩次之間沒有什麼關係(不考慮快取),不會像你去親戚家串門,上次去了,這次就認識你了。要想讓它們有關係我們注意到request header和resonse header都有cookie,Session等客戶端狀態維護就是基於此實現的。

3.在請求時並不是頁面所有內容都被髮往伺服器

4.在客戶端就已經沒有什麼伺服器端控制元件、方法、屬性了,只有HTML文字

幾個問題

總而言之有一句需要注意:HTTP協議並不是瀏覽器把整個頁面發給伺服器,然後讓伺服器做少許改動傳回給瀏覽器,而是瀏覽器傳送少量資料引數傳給伺服器,伺服器根據特定頁面規則和瀏覽器引數生成全新頁面傳回給瀏覽器,瀏覽器更新載入這個全新頁面(不考慮Ajax)。瀏覽器呈現的頁面和伺服器之間並不能通過所謂呼叫來互動。

理論知識就這麼多,下一篇中就要即使一下開頭提的三個問題了,修改羅列一下

1.伺服器端如何影響客戶端元素與行為

2.客戶端如何”呼叫“伺服器端方法

3.JavaScript如何操作伺服器控制元件render的HTML,以實現互動

PS:如果還有同學對HTTP協議有疑惑,可以看看之前為了跟小夥兒伴們將HTTP而寫的一個課件

相關文章