利用Response.Flush和iframe實現”服務器推”技術

      通過在HTML頁面裏陷入一個隱藏的iframe,然後將這個iframe的src屬性設爲對一個長連接的請求(利用chunked傳輸response),服務器端就能源源不斷地往客戶推送數據。

      基於流方式的”服務器推”模型:

image

       服務端在接到客戶端的請求時,通過Response的Flush()方法發送數據,可以使用定時器的方式發送數據,沒有數據也發送”無數據”,讓客戶端保持長連接,直至客戶端斷開連接,請求結束。每次數據傳送不會關閉連接,連接只會在通信出現錯誤時,或是連接重建時關閉(一些防火牆常被設置爲丟棄過長的連接, 服務器端可以設置一個超時時間, 超時後通知客戶端重新建立連接,並關閉原來的連接)。

      實現代碼:

      頁面Default.aspx,用來展示數據:

1:     數據列表:o<br />
2:     <div id="con" style=" width:400; height:200px; border:1px solid #FF0">
3:     </div>
4:     <iframe id="flush" src="Flush.aspx" style=" display:none" />
5:  

 

     ifame的src對應的Flash.aspx後臺代碼,模擬後臺發送數據:

 1:  protected void Page_Load(object sender, EventArgs e)
 2:      {
 3:          string startHTML = "<!DOCTYPE HTML PUBLIC /"-//W3C//DTD XHTML 1.0 Transitional//EN/" /"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd/">" + Environment.NewLine
 4:              + "<html xmlns=/"http://www.w3.org/1999/xhtml/" >" + Environment.NewLine
 5:              + "<head>" + Environment.NewLine
 6:              + "</head>" + Environment.NewLine
 7:              + "<body>" + Environment.NewLine;
 8:   
 9:          startHTML += new String(' ', 1024) + Environment.NewLine;
10:   
11:          Response.Write(startHTML);
12:          Response.Flush();
13:   
14:          string data = "<script type=/"text/javascript/">parent.$('#con').append(/"{0}/");</script>";
15:          Response.Write(string.Format(data, "開始發送數據:<br/>"));
16:          Response.Flush();
17:   
18:          int index = 0;
19:          while (true)
20:          {
21:              System.Threading.Thread.Sleep(2000);
22:              if (index % 2 == 0)
23:              {
24:                  Response.Write(string.Format(data, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " 服務端發送數據<br/>"));
25:              }
26:              else
27:              {
28:                  Response.Write(string.Format(data, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " 無數據發送<br/>"));
29:              }
30:              Response.Flush();
31:   
32:              index++;
33:          }
34:      }
35:   

 

      運行Default.aspx的結果:

image

      使用 iframe 請求一個長連接有一個很明顯的不足之處:IE、Morzilla Firefox 下端的進度欄都會顯示加載沒有完成,而且 IE 上方的圖標會不停的轉動,表示加載正在進行;刷新當前頁面反應也是會很慢。

      解決IE的進度欄顯示加載沒有完成,可以使用一個稱爲“htmlfile”的 ActiveX,是Google 的天才們使用的方法,該控件也被用到gmail+gtalk 產品中。

      修改Default.aspx的頁面代碼:

 1:  數y據Y列D表í:o<br />
 2:     <div id="con" style=" width:400; height:200px; border:1px solid #FF0">
 3:     </div>
 4:      <script type="text/javascript">
 5:          function getData(d)
 6:          {
 7:              $("#con").append(d);
 8:          }
 9:   
10:          function rpc_iframe() {
11:              var transferDoc = new ActiveXObject("htmlfile");
12:              transferDoc.open();
13:              transferDoc.write("<html>")
14:              transferDoc.write("<div><iframe src=/"Flush.aspx/"></iframe></div>");
15:              transferDoc.close("</html>");
16:              transferDoc.parentWindow.getData = getData;
17:              setInterval(function () { }, 10000);  //不加這句會使連接斷開
18:          }
19:   
20:          rpc_iframe();
21:     </script>
22:  

 

     修改Flush.aspx.cs代碼:

1:  //string data = "<script type=/"text/javascript/">parent.$('#con').append(/"{0}/");</script>";
2:          string data = "<script type=/"text/javascript/">parent.getData(/"{0}/");</script>";
3:   
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章