[转载]HTTP PUSH技术原理,结合ASP.NET实现以及评述
HTTP PUSH技術原理,結合ASP.NET實現以及評述?收藏
原文:http://blog.csdn.net/banmuhuangci/archive/2008/09/20/2955719.aspx
?
??前段時間看到有人寫的關于HTTP PUSH原理,當初并不在意,因為HTTP的先天問題,WEB服務器不可能主動PUSH因為HTTP響應過后就斷開連接,WEB服務器不可能再觸發什么事件后對某個客戶端瀏覽器進行PUSH信息的。
??? 最近閑在家中,又突然想起這件事情,雖然說自我感覺這并不是正統的PUSH技術,但是畢竟已經有人在用,而且效果還不錯,不如自己也來試試看。經過小小嘗試,發現其實HTTP PUSH其實是一個很簡單的原理,但效果確實不錯,不過也有點需要解決的問題。
????廢話不說了,前面唐生了一段,入正題。
?
????首先闡述一下HTTP PUSH的原理,眾所周知,HTTP是無狀態的,瀏覽器在REUQEST之后,WEB服務器做出處理,然后將處理結果RESPONSE到瀏覽器,完成后斷開連接。在請求之前和完成之后,WEB服務器和瀏覽器之間沒有任何關系,互不相干。因此我們在做聊天室等需要不斷從服務器獲取新數據的應用的時候,都是采用不斷的去請求服務器,當然,AJAX的出現讓用戶體驗直線上升不過仍然是不斷去請求,只是用戶不知道而已。這樣看來,WEB服務器怎么PUSH啊?天方夜譚!每次請求都是獨立的,無狀態的,不過,如果說數據不斷的更新其實就是一次請求呢?通常情況下,從REQUEST 到RESPONSE,WEB服務器只是干一系列的事后發出一次結果,時間上是比較短的,同時,REQUEST到RESPONSE這個過程中瀏覽器和服務器是有鏈接的。是的,這就是突破口,利用一個非正常的手段,延長從REQUEST到RESPONSE的時間,我們就可以獲得這段時間的鏈接狀態,讓服務器在這段時間里都做些事情并立刻將進行中的結果發送過來而非等待全部完成后發送。
????
????打個比方,一個人去郵局拿信,該郵局不會主動送信到家,每小時一次,到郵局后,他詢問工作人員有沒有他的信,無論有沒有他都會回家,然后下i個小時再去問,周而復始,這就是通常的WEB聊天用的方法,瀏覽器定時去REQUEST,然后獲得RESPONSE結束。現在我們換個方法,這個人不是每個小時去一次,而是打了個地鋪長期睡在郵局里,他告訴郵局工作人員一有信就交給他,一旦有信,他就馬上叫郵遞員把信放到他家郵箱,這時候他坐在家里的老婆就會感覺到郵局現在是主動把信發到他家里了。這下明白了吧,就這么回事。
?
????下面是我用ASP.NET實現的一個小例子,比較簡單。
?
首先要建立兩個頁面,一個是用來更新信息,更新服務器上一個公共區域的信息。令一個頁面就將用到PUSH方法,接收信息,當檢查到服務器上公共區域的信息發生變化,服務器就立刻做出反應并把信息發送到頁面上。本例中,ASPX頁面不需要任何的客戶端腳本,所以就不貼前臺頁面的代碼了。
?
下面是代碼:
?
發送端:
??? protected void Page_Load(object sender, EventArgs e)
??? {
??????? Application["msg"] += "new date:" + DateTime.Now.ToString()+"<br>";
??????? Response.Write(Application["msg"]);
??? }
?
為了能夠方便的刷新頁面來更新數據,可以加以個BUTTON按鈕。
?
接收端:
?
?protected void Page_Load(object sender, EventArgs e)
??? {
??????? Response.Buffer = true;
??????? if (Page.IsPostBack)
??????? {
????????????
??????????? while (Response.IsClientConnected)
??????????? {
??????????????? System.Threading.Thread.Sleep(1000);
??????????????? if (Application["msg"] != Session["Current"])
??????????????? {
??????????????????? Session["Current"] = Application["msg"];
??????????????????? Response.Write(Session["Current"].ToString());
??????????????????? Response.Flush();
??????????????? }
??????????????? else
??????????????? {
??????????????????? Response.Write(".");
??????????????????? Response.Flush();
??????????????? }
??????????? }
?
??????? }
??????? else
??????? {
??????????? Session["Current"] = "";
??????????? Response.Write("Do on Request!<br>");
??????? }
????}
?
這里同樣要在ASPX上加一個按鈕,頁面第一次加載后,點按鈕進行第2次請求,第2次請求就將成為長請求。
?
?
下面進行一下代碼說明,更新信息頁沒什么好說的,我用的是APPLICATION,方便點,當然也可以用數據庫XML等之類的。
?
主要說下接手頁。首先我們將該頁面的Response.Buffer設置為ture,這樣可以穩妥的控制好在我們不同意的情況下Response數據是保留在內存中的,當Page.IsPostBack時,說明是第2次請求了也就是要執行長請求了,用以個 while循環,條件是Response.IsClientConnect成立,也就是用戶沒有離開次頁面,也沒有停止請求的時候都一直循環,循環什么呢?循環檢查當前用戶的Session里的信息是否和Application全局變量里的信息相同,如果相同那么說明沒有新的信息更新,立即輸出一個“.”(為了測試方便設置的,其實可以什么都不做),當信息不同的時候,說明有更新了,因此就將Application里的東西復制給Session并將Session立即輸出。OK 完成,我們可以測試一下,打開兩個窗口,一個加載更新頁,一個加載接收頁,點擊接收頁的按鈕讓它開始執行長請求,這時候接收也應該是空當當的,然后我們點擊更新頁,頁面新出現了我們執行請求的一行時間,再切換到接收頁,YEAH,接收頁立刻也出現了這個時間。這里要提個非常重要的東西,Response.Flush()方法,這個方法不是太經常用,但是很好用,作用是不需要等待請求完成立刻將內存中的結果輸出到瀏覽器,這是PUSH相當重要的一個環節,因為我們本來就是要求請求是要長時間等待的,所以不可能讓數據在請求完成后再發送,因此要利用FLUSH將數據立刻發送,這就是那個男人請的那個郵遞員。另外還有一個重要的地方,System.Threading.Thread.Sleep(1000),這里我設置了沒次循環讓當前線程休息一秒,為什么呢?實際上用while的話,用戶不離開這個請求就是完成不了的,一直等待著的,Thread.Sleep在這里并不是用來控制時間,而是保證CPU到使用率,去掉這句運行的話你會發現你的CPU永遠100%,太頻繁的檢查更新非常消耗服務器資源,因此應該給個停頓時間, 郵局找信那家伙也是人別讓人家累病了。
?
這樣,一個長請求,也就是讓WEB服務器PUSH信息的小例子就做好了,當然這個例子并不完善,不過用來了解工作原理還是很直觀的。
?
不過,這個方法會阻塞線程,我們會發現,請求線程是一直被掛起的,因此同一個會話用戶就無法再去請求這個服務器的其他資源了,因為同一個會話用戶的請求線程服務器會讓你等待之前的那個線程完成后再去執行,而那個線程被我們設置成了不會完成或者很長時間才能完成,這就好比,那個男人的老婆想讓老公去幫他買晚餐的菜,可是他的老公卻在郵局回不來。也許有人會想建立一個新的線程去做等待的事情或新的事情不就可以了嗎?問題是,雇用保姆的工作也需要那個男人去做..........
?
目前為止本例沒有解決關于阻塞線程的問題,我能想到的方法就是讓被阻塞的線程與其他請求線程分開不在同一個會話里或不在同一個本請求的服務器上。這也是為什么在測試本例的時候要求先打開兩個窗口。
?
好了,HTTP PUSH的原理和例子到目前我理解的就這些了,也許今后HTTPPUSH會有很好的改良或許現在就有,多學習多思考很重要。最后付上一個圖例,更直觀的理解HTTP PUSH
?
?
通常情況:瀏覽器REQUEST—>服務器處理—>服務器RESPONSE到瀏覽器
?
長請求PUSH:瀏覽器REQUEST—>服務器處理<===========>服務器RESPONSE到瀏覽器——————>最終
轉載于:https://www.cnblogs.com/DrWang/archive/2010/08/24/1807052.html
總結
以上是生活随笔為你收集整理的[转载]HTTP PUSH技术原理,结合ASP.NET实现以及评述的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Oracle视图的作用与安全性
- 下一篇: 内联函数与普通函数、成员函数与静态函数的