在B/S架构的系统中,一般都是由客户端发起请求,然后服务器端作出回应。随着html5的兴起,现在应用html5的服务器推送技术Server-Sent Events可以实现由服务器端直接推送信息给客户端。
客户端接收信息页面a.html:(客户端打开该页面即可接收来自服务器端推送的消息,如果a页面与服务器的连接中断,会自动重新连接)
<html>
<head>
<title>客户端接收信息页面</title>
</head>
<body>
<script language="javascript" type="text/javascript">
if (!!window.EventSource) {
var source = new EventSource('a.ashx');
source.addEventListener('message', function (e) {
var event = JSON.parse(e.data);
console.log(event.msg);
}, false);
source.addEventListener("meeting", function (e) {
var event = JSON.parse(e.data);
if ("closed" == event.status) {
console.log("the meeting is closed");
source.close();
}
console.log(event.msg+"dddd");
}, false)
var currPage;
source.addEventListener("page", function (e) {
var event = JSON.parse(e.data);
alert(event.turnTo);
if (currPage != event.turnTo) {
console.log("turn to page " + event.turnTo);
currPage = event.turnTo;
} // else ignore the double message
}, false);
}
else {
alert("EventSource is not supported, using xhr polling instead");
}
</script>
</body>
</html>
服务器推送信息页面b.ashx:(a.html运行后会请求该服务程序,该服务每隔10s会推送一次消息给a.html页面)
<%@ WebHandler Language="C#" Class="test" %>
using System;
using System.Web;
using System.Threading;
using System.Collections.Generic;
using Framework.Common.Extensions;
public class test : IHttpHandler {
public void ProcessRequest (HttpContext context) {
List<HttpContext> contextList = (List<HttpContext>)context.Application["ContextList"];
if (null == contextList)
{
contextList = new List<HttpContext>();
}
contextList.Add(context); //记录客户端连接信息,用于后面推送信息给客户端,要不就不知道发送给谁了哦
context.Application["ContextList"] = contextList;
while(false==context.Application["meeting-closed"].ToPrimitiveType<bool>()) //在这里无限等待,直到有请求告知要关闭
{
if (context.Response.IsClientConnected)
{
context.Response.ContentType = "text/event-stream";
context.Response.CacheControl = "no-cache";
for (int i = 0; i < 2; i++)
{
context.Response.Write(string.Concat("event: ", "meeting", "\n"));
context.Response.Write("data: {\"msg\": \"keep-alive" + DateTime.Now.ToString() + "\"}\n\n");
context.Response.Flush();
}
}
Thread.Sleep(10000); //每隔10s往客户端发送一次消息
}
if (context.Response.IsClientConnected == true)
{
context.Response.Close();
}
}
public bool IsReusable {
get {
return false;
}
}
}
客户端主动要求推送消息页面c.aspx:(点击保存按钮后,a.html页面即可马上接收到由服务器发送过来的消息)
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="c.aspx.cs" Inherits="test" %>
<!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:TextBox ID="txtPage" runat="server" Text=""></asp:TextBox>
<asp:Button ID="btnTurnPage" runat="server" Text="保存"
οnclick="btnTurnPage_Click" />
</div>
</form>
</body>
</html>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
public partial class test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnTurnPage_Click(object sender, EventArgs e)
{
List<HttpContext> contextList = (List<HttpContext>)Application["ContextList"];
if (null != contextList)
{
contextList.ForEach(context => //循环看有多少存在连接的客户端需要推送消息
{
HttpResponse response = context.Response;
if (true == response.IsClientConnected)
{
//context.Response.ContentType = "text/event-stream";
//context.Response.CacheControl = "no-cache";
for (int i = 0; i < 2; i++)
{
response.Write(string.Concat("event: ", "page", "\n"));
response.Write("data: {\"turnTo\": \"" + this.txtPage.Text.Trim() + "\"}\n\n");
response.Flush();
}
}
});
}
}
}
感谢美丽达人的鼎力支持!