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

作者: Asharp  來源: 博客園  發布時間: 2010-09-19 07:25  閱讀: 2673 次  推薦: 0   原文鏈接   [收藏]  
摘要:通過在HTML頁面里陷入一個隱藏的iframe,然后將這個iframe的src屬性設為對一個長連接的請求(利用chunked傳輸response),服務器端就能源源不斷地往客戶推送數據。

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

image

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

  實現代碼:

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

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

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

 
protected void Page_Load(object sender, EventArgs e)
{
string startHTML = "
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">" + Environment.NewLine
+ "
<html xmlns=\"http://www.w3.org/1999/xhtml\" >" + Environment.NewLine
+ "
<head>" + Environment.NewLine
+ "
</head>" + Environment.NewLine
+ "
<body>" + Environment.NewLine;
startHTML += new String(' ', 1024) + Environment.NewLine;

Response.Write(startHTML);
Response.Flush();
string data = "
<script type=\"text/javascript\">parent.$('#con').append(\"{0}\");</script>";
Response.Write(string.Format(data, "開始發送數據:
<br/>"));
Response.Flush();
int index = 0;
while (true)
{
System.Threading.Thread.Sleep(2000);
if (index % 2 == 0)
{
Response.Write(string.Format(data, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " 服務端發送數據
<br/>"));
}
else
{
Response.Write(string.Format(data, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + " 無數據發送
<br/>"));
}
Response.Flush();

index++;
}
}

  運行Default.aspx的結果:

image

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

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

  修改Default.aspx的頁面代碼:

 
數y據Y列D表í:o<br />
<div id="con" style=" width:400; height:200px; border:1px solid #FF0">
</div>
<script type="text/javascript">
function getData(d)
{
$("#con").append(d);
}
function rpc_iframe() {
var transferDoc = new ActiveXObject("htmlfile");
transferDoc.open();
transferDoc.write("<html>")
transferDoc.write("<div><iframe src=\"Flush.aspx\"></iframe></div>");
transferDoc.close("</html>");
transferDoc.parentWindow.getData = getData;
setInterval(function () { }, 10000); //不加這句會使連接斷開
}
rpc_iframe();
</script>

  修改Flush.aspx.cs代碼:

 
//string data = "<script type=\"text/javascript\">parent.$('#con').append(\"{0}\");</script>";
string data = "
<script type=\"text/javascript\">parent.getData(\"{0}\");</script>";
0
0
 
標簽:ASP.NET
 
 

文章列表

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()