62,025
社区成员
发帖
与我相关
我的任务
分享
//告警更新订阅
Application.Add("AlarmsUpdateSubscrib", new CSubscrib());
//实时数据更新订阅
Application.Add("DatasUpdateSubscrib", new CSubscrib());
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
namespace TieTaOMC
{
/// <summary>
/// 订阅类
/// </summary>
public class CSubscrib
{
/// <summary>
/// 订阅响应信息对象字典
/// </summary>
private Dictionary<long, HttpResponse> m_Response;
/// <summary>
/// 订阅类实例
/// </summary>
public CSubscrib()
{
m_Response = new Dictionary<long, HttpResponse>();
}
/// <summary>
/// 添加订阅
/// </summary>
/// <param name="lResponseID">响应信息对象编号</param>
/// <param name="htpResponse">响应信息对象</param>
/// <returns>是否成功</returns>
public bool addResponse(long lResponseID, HttpResponse htpResponse)
{
bool bReturn = false;
if (0 < lResponseID && null != htpResponse)
{
if (!m_Response.ContainsKey(lResponseID))
{
m_Response.Add(lResponseID, htpResponse);
bReturn = true;
}
}
return bReturn;
}
/// <summary>
/// 删除订阅
/// </summary>
/// <param name="lResponseID">响应信息对象编号</param>
/// <returns>是否成功</returns>
public bool delResponse(long lResponseID)
{
bool bReturn = false;
if (0 < lResponseID)
{
if (m_Response.ContainsKey(lResponseID))
{
//m_Response[lResponseID].Close();
bReturn = m_Response.Remove(lResponseID);
}
}
return bReturn;
}
/// <summary>
/// 发送订阅信息
/// </summary>
/// <param name="lResponseID">响应信息对象编号</param>
/// <param name="sMessage">信息字符串</param>
/// <param name="bCheckExsist">是否检查存在,默认为不检查</param>
/// <returns>是否成功</returns>
public bool sendSubscribMessage(long lResponseID, string sMessage, string sObjID, bool bCheckExsist = false)
{
bool bReturn = false;
if (0 < lResponseID && null != sMessage && 0 < sMessage.Length)
{
bool bExsist = true;
if (bCheckExsist)
{
bExsist = m_Response.ContainsKey(lResponseID);
}
if (bExsist)
{
try
{
HttpResponse htpResponse = m_Response[lResponseID];
htpResponse.Write("data: " + sObjID + "\n");
htpResponse.Write("data: " + sMessage + "\n\n");
htpResponse.Flush();
}
catch (System.Exception ex)
{
string sError = ex.Message;
sError = "";
}
bReturn = true;
}
}
return bReturn;
}
/// <summary>
/// 向所有的订阅响应信息对象发送信息
/// </summary>
/// <param name="sMessage"></param>
/// <returns></returns>
public bool sendSubscribMessageToAllResponses(string sMessage, string sObjID)
{
bool bReturn = false;
if (null != sMessage && 0 < sMessage.Length)
{
bReturn = true;
foreach (long lResponseID in m_Response.Keys)
{
sendSubscribMessage(lResponseID, sMessage, sObjID);
}
}
return bReturn;
}
}
public class Global : System.Web.HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
// 在应用程序启动时运行的代码
//告警更新订阅
Application.Add("AlarmsUpdateSubscrib", new CSubscrib());
//实时数据更新订阅
Application.Add("DatasUpdateSubscrib", new CSubscrib());
}
void Application_End(object sender, EventArgs e)
{
// 在应用程序关闭时运行的代码
}
void Application_Error(object sender, EventArgs e)
{
// 在出现未处理的错误时运行的代码
}
void Session_Start(object sender, EventArgs e)
{
// 在新会话启动时运行的代码
}
void Session_End(object sender, EventArgs e)
{
// 在会话结束时运行的代码。
// 注意: 只有在 Web.config 文件中的 sessionstate 模式设置为
// InProc 时,才会引发 Session_End 事件。如果会话模式设置为 StateServer
// 或 SQLServer,则不会引发该事件。
}
}
}
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="AlarmList.aspx.cs" Inherits="TieTaOMC.Subscrib.AlarmList" %>
<!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 id="Head1" runat="server">
<title>获得服务器更新</title>
<script language="javascript" type="text/javascript" src="Scripts/jquery-1.4.1.min.js"></script>
</head>
<body>
<h1>获得服务器更新</h1>
<asp:Label ID="SessionKey" runat="server" Text="Label"></asp:Label>
<div id="Table_Div" style="width: 100%">
<table id="alarmsListTable" width="100%" border="1" cellspacing="0" cellpadding="2">
<tr align="center">
<td nowrap>告警序号</td>
<td nowrap>告警站点编号</td>
<td nowrap>告警设备</td>
<td nowrap>告警编号</td>
<td nowrap>告警级别</td>
<td nowrap>告警内容</td>
<td nowrap>告警时间</td>
<td width="100%"> </td>
</tr>
</table>
</div>
<div id="resultDiv">aaaaa</div>
<div id="errorDiv">aaaaa</div>
<script language="javascript" type="text/javascript">
var iAlarmsCount = 0;
if (typeof (EventSource) !== "undefined") {
var sURL = "AlarmsUpdateSubscrib.ashx";
var source = new EventSource(sURL);
source.onmessage = function (event) {
var sData = "";
$("#errorDiv").html("");
sData = event.data;
$("#resultDiv").text(sData);
var sArray = sData.split('\n');
var sID = "#" + sArray[0] + " tr:eq(0)";
$(sArray[1]).insertAfter($(sID));
};
source.onerror = function (event) {
$("#errorDiv").html("<br />错误:<br />");
};
}
else {
$("#errorDiv").html("错误:<br />对不起,您的浏览器不支持“HTML5 服务器发送事件(server-sent event)允许网页获得来自服务器的更新”。<br />");
}
</script>
</body>
</html>
编译工程,然后运行工程
打开的浏览器地址栏中输入http://localhost:xxxx/AddAlarm.aspx,然后回车,其中“xxxx”为工程调试时的服务端口(我的为4239),定义为告警添加页面。
然后另外打开一个页面,在地址栏中输入http://localhost:xxxx/AlarmList.aspx,然后回车,其中“xxxx”同上,定义为告警列表页面,也可以在局域网中的另一台计算机上进行本操作,效果一样。
在告警添加页面中填写如下图所示的内容:
然后点击“提交”按钮
然后查看告警列表画面,画面如下图所示:
如果是本机运行两个页面的话,通过cmd的netstat命令我们可以发现其中两行内容
TCP [::1]:4239 lizhimin-PC:6945 ESTABLISHED
TCP [::1]:6945 lizhimin-PC:4239 ESTABLISHED
如下图所示:
说明server-sent events在告警列表页面通过var source = new EventSource(sURL);产生的客户端端口为“6945”,请求的服务端AlarmsUpdateSubscrib.ashx端口为4239,状态为ESTABLISHED表明该socket连接正在存在,是个长连接,客户端一直等待服务端推送数据。
当然在不同的计算机上,计算机名称可能不一样,端口号不一样但是肯定会出现形如以上的两行内容。
在此有个问题,如果客户端太多,服务器所建立的长连接太多,这样会耗费很多资源,怎么解决这个问题呢?是不是要定时删除几个Response,然后重新连接?如果数据量很大的话,这样做的代价和一直保持连接,孰轻孰重?有待于研究。
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="AddAlarm.aspx.cs" Inherits="TieTaOMC.AddAlarm" %>
<!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="alarmForm" runat="server">
<asp:Table ID="alarmTable" runat="server">
<asp:TableRow>
<asp:TableCell Wrap="False">告警流水号:
</asp:TableCell>
<asp:TableCell>
<asp:TextBox ID="txt_AlarmSerialNo" runat="server"></asp:TextBox>
</asp:TableCell>
<asp:TableCell>站点编号:
</asp:TableCell>
<asp:TableCell>
<asp:TextBox ID="txt_FSUNo" runat="server"></asp:TextBox>
</asp:TableCell>
<asp:TableCell Wrap="False">子设备名称:
</asp:TableCell>
<asp:TableCell>
<asp:TextBox ID="txt_DevName" runat="server"></asp:TextBox>
</asp:TableCell>
<asp:TableCell Width="100%">
</asp:TableCell>
</asp:TableRow>
<asp:TableRow>
<asp:TableCell Wrap="False">告警编号:
</asp:TableCell>
<asp:TableCell>
<asp:TextBox ID="txt_AlarmNo" runat="server"></asp:TextBox>
</asp:TableCell>
<asp:TableCell Wrap="False">告警级别:
</asp:TableCell>
<asp:TableCell>
<asp:TextBox ID="txt_AlarmLevel" runat="server"></asp:TextBox>
</asp:TableCell>
<asp:TableCell Wrap="False">告警描述:
</asp:TableCell>
<asp:TableCell>
<asp:TextBox ID="txt_AlarmDesc" runat="server"></asp:TextBox>
</asp:TableCell>
<asp:TableCell>
</asp:TableCell>
</asp:TableRow>
<asp:TableRow>
<asp:TableCell Wrap="False" ColumnSpan="7">
<asp:Button ID="but_OK" runat="server" Text="提交" OnClick="but_Add_Click" />
</asp:TableCell>
</asp:TableRow>
</asp:Table>
</form>
</body>
</html>
AddAlarm.aspx.cs内容
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace TieTaOMC
{
public partial class AddAlarm : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void but_Add_Click(object sender, EventArgs e)
{
string sAlarmSerialNo = "", sFSUNo = "", sDevName = "", sAlarmNo = "", sAlarmLevel = "", sAlarmDesc = "";
sAlarmDesc = txt_AlarmDesc.Text;
sAlarmLevel = txt_AlarmLevel.Text;
sAlarmSerialNo = txt_AlarmSerialNo.Text;
sDevName = txt_DevName.Text;
sFSUNo = txt_FSUNo.Text;
sAlarmNo = txt_AlarmNo.Text;
if(
0 < sAlarmDesc.Length ||
0 < sAlarmLevel.Length ||
0 < sAlarmNo.Length ||
0 < sAlarmSerialNo.Length ||
0 < sDevName.Length ||
0 < sFSUNo.Length)
{
//告警更新订阅
CSubscrib AUpdateSubscrib = Application.Get("AlarmsUpdateSubscrib") as CSubscrib;
if (null != AUpdateSubscrib)
{
string sTRS = "<tr>", sTDs = "<td nowrap> ", sTDE = "</td>", sTRE = "</tr>";
string sHTML = sTRS;
sHTML += sTDs + sAlarmSerialNo + sTDE; //告警序号
sHTML += sTDs + sFSUNo + sTDE; //告警站点编号
sHTML += sTDs + sDevName + sTDE; //告警设备
sHTML += sTDs + sAlarmNo + sTDE; //告警编号
sHTML += sTDs + sAlarmLevel + sTDE; //告警级别
sHTML += sTDs + sAlarmDesc + sTDE; //告警内容
sHTML += sTDs + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + sTDE; //告警时间
sHTML += sTDs + sTDE;
sHTML += sTRE;
AUpdateSubscrib.sendSubscribMessageToAllResponses(sHTML, "alarmsListTable");
}
}
}
}
}
public void ProcessRequest(HttpContext context)
{
HttpApplicationState App = context.Application;
if (null != App)
{
HttpResponse response = context.Response;
if (null != response)
{
long lngSessionID = 1;
int iSleepSpace = 1000/*while循环线程睡眠毫秒数*/;
Random ra = new Random();
lngSessionID += ra.Next();
response.ContentType = "text/event-stream";
//告警更新订阅
CSubscrib AUpdateSubscrib = App.Get("AlarmsUpdateSubscrib") as CSubscrib;
if (null != AUpdateSubscrib && AUpdateSubscrib.addResponse(lngSessionID, response))
{
while (response.IsClientConnected)
{
Thread.Sleep(iSleepSpace);
}
}
response.End();
response.Close();
}
}
}
AlarmsUpdateSubscrib.ashx.cs内容
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Threading;
namespace TieTaOMC
{
/// <summary>
/// 告警更新订阅类
/// </summary>
public class AlarmsUpdateSubscrib : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
HttpApplicationState App = context.Application;
if (null != App)
{
HttpResponse response = context.Response;
if (null != response)
{
long lngSessionID = 1;
int iSleepSpace = 1000/*while循环线程睡眠毫秒数*/;
Random ra = new Random();
lngSessionID += ra.Next();
response.ContentType = "text/event-stream";
//告警更新订阅
CSubscrib AUpdateSubscrib = App.Get("AlarmsUpdateSubscrib") as CSubscrib;
if (null != AUpdateSubscrib && AUpdateSubscrib.addResponse(lngSessionID, response))
{
while (response.IsClientConnected)
{
Thread.Sleep(iSleepSpace);
}
}
response.End();
response.Close();
}
}
}
public bool IsReusable
{
get
{
return false;
}
}
}
}