Asp classic 使用经典ASP的服务器发送事件(SSE):实现LastEventID并支持多个侦听器
显然,由于Internet Explorer不支持服务器发送的事件,所以为经典ASP编写的示例很少。大多数已发布的示例都使用NodeJS或PHP,但本网站和其他网站上的文章指出或暗示可以使用任何中间件语言 我已经获得了使用ASP(使用VBS)的基本代码,但确实不了解两件事:如何将最新的EventID成功发送到特定的侦听器,以及我的代码需要在多大程度上(如果有的话)跟踪当前侦听器的列表。完全公开——我对这种代码没有什么“感觉”。例如,我花了一段时间才意识到,从服务器发送的“消息”只是使用常规文本输出的语法,即Response.Write 好的,在我问两个问题之前,这里是我正在使用的代码。这是我找到的一个PHP示例()。它从正在读取的数组中输出值(看起来像股票价格数据)。在php示例中,sleep()函数用于在事件之间设置延迟。在asp中,我使用了一种在评论(见下文)中向我建议的不同技术,它产生大约3秒的同步延迟。 下面是服务器端ASP代码:Asp classic 使用经典ASP的服务器发送事件(SSE):实现LastEventID并支持多个侦听器,asp-classic,server-sent-events,eventsource,Asp Classic,Server Sent Events,Eventsource,显然,由于Internet Explorer不支持服务器发送的事件,所以为经典ASP编写的示例很少。大多数已发布的示例都使用NodeJS或PHP,但本网站和其他网站上的文章指出或暗示可以使用任何中间件语言 我已经获得了使用ASP(使用VBS)的基本代码,但确实不了解两件事:如何将最新的EventID成功发送到特定的侦听器,以及我的代码需要在多大程度上(如果有的话)跟踪当前侦听器的列表。完全公开——我对这种代码没有什么“感觉”。例如,我花了一段时间才意识到,从服务器发送的“消息”只是使用常规文本输
<%@ LANGUAGE="VBSCRIPT" %>
<%
Dim demoarr(21,1)
demoarr(0,0) = "GOOG"
demoarr(0,1) = 533.37
demoarr(1,0) = "MSFT"
demoarr(1,1) = 47.59
demoarr(2,0) = "IBM"
demoarr(2,1) = 162.99
demoarr(3,0) = "AAPL"
demoarr(3,1) = 114.12
demoarr(4,0) = "MSFT"
demoarr(4,1) = 47.29
demoarr(5,0) = "GOOG"
demoarr(5,1) = 533.95
demoarr(6,0) = "IBM"
demoarr(6,1) = 163.78
demoarr(7,0) = "GOOG"
demoarr(7,1) = 533.55
demoarr(8,0) = "AAPL"
demoarr(8,1) = 113.67
demoarr(9,0) = "GOOG"
demoarr(9,1) = 533.91
demoarr(10,0) = "MSFT"
demoarr(10,1) = 48.12
demoarr(11,0) = "IBM"
demoarr(11,1) = 162.37
demoarr(12,0) = "AAPL"
demoarr(12,1) = 114.12
demoarr(13,0) = "MSFT"
demoarr(13,1) = 48.05
demoarr(14,0) = "AAPL"
demoarr(14,1) = 114.32
demoarr(15,0) = "GOOG"
demoarr(15,1) = 533.97
demoarr(16,0) = "MSFT"
demoarr(16,1) = 48.54
demoarr(17,0) = "IBM"
demoarr(17,1) = 162.69
demoarr(18,0) = "AAPL"
demoarr(18,1) = 114.45
demoarr(19,0) = "IBM"
demoarr(19,1) = 162.74
demoarr(20,0) = "AAPL"
demoarr(20,1) = 114.67
response.ContentType = "text/event-stream"
response.AddHeader "Cache-Control", "no-cache"
response.AddHeader "Connection", "keep-alive"
lastID = 0
pickstock = 0
Do While True
pickstock = (pickstock + 1) MOD 20
lastid = lastid + 2
sendMessage lastId, demoarr(pickstock,0), demoarr(pickstock,1)
sendMessage lastId+1, demoarr(pickstock,0), demoarr(pickstock,1)
x = sleep(3)
Loop
Function sendMessage(id, ticket, price)
Response.Write "id: " & id & vbcrlf & vbcrlf
response.flush
Response.Write "data: " & ticket & ":" & price & vbcrlf & vbcrlf
response.flush
End Function
Function sleep(scs)
Dim lo_wsh, ls_cmd
Set lo_wsh = CreateObject( "WScript.Shell" )
ls_cmd = "%COMSPEC% /c ping -n " & 1 + scs & " 127.0.0.1>nul"
lo_wsh.Run ls_cmd, 0, True
End Function %>
下面是客户端html/javascript:
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Server Sent Events ASP Example - Stock Tickets</title>
<style media="screen" type="text/css">
H1 {
text-align: center;
font-size: 150%;
margin-bottom: 60px;
}
H2 {
text-align: center;
font-size: 125%;
margin-bottom: 15px;
}
DIV#tickets {
margin: 10px auto 80px auto;
}
DIV.ticket {
margin: 5px auto;
width: 160px;
font-size: 115%;
}
DIV.name {
display: inline-block;
width: 80px;
padding: 3px;
}
DIV.price {
display: inline-block;
width: 60px;
padding: 3px;
text-align: right;
transition: all 0.2s ease-out;
}
DIV#log {
margin: 10px auto;
width: 600px;
height: 200px;
background: gainsboro;
padding: 5px;
overflow-y: scroll;
}
DIV#notSupported {
display: none;
margin: 10px auto;
text-align: center;
color: red;
font-size: 150%;
}
P.hint {
width: 600px;
margin: 10px auto;
text-align: justify;
text-indent: 20px;
line-height: 135%;
}
DIV#download {
margin: 50px auto;
text-align: center;
}
DIV#download A {
padding: 10px 25px;
background: #F1592A;
color: white;
text-decoration: none;
font-size: 20px;
border-radius: 5px 5px;
}
DIV#download A:hover {
text-decoration: underline;
background: #FF592A;
}
</style>
<script type="text/javascript">
window.onload = function setDataSource() {
if (!!window.EventSource) {
var source = new EventSource("stocks.asp");
source.addEventListener("message", function(e) {
updatePrice(e.data);
logMessage(e);
}, false);
source.addEventListener("open", function(e) {
logMessage("OPENED");
}, false);
source.addEventListener("error", function(e) {
logMessage("ERROR");
if (e.readyState == EventSource.CLOSED) {
logMessage("CLOSED");
}
}, false);
} else {
document.getElementById("notSupported").style.display = "block";
}
}
function updatePrice(data) {
var ar = data.split(":");
var ticket = ar[0];
var price = ar[1];
var el = document.getElementById("t_" + ticket);
var oldPrice = el.innerHTML;
el.innerHTML = price;
if (parseFloat(oldPrice) < parseFloat(price)) {
el.style.backgroundColor = "lightgreen";
} else {
el.style.backgroundColor = "tomato";
}
window.setTimeout(function clearBackground() {
el.style.backgroundColor = "white";
}, 500);
}
function logMessage(obj) {
var el = document.getElementById("log");
if (typeof obj === "string") {
el.innerHTML += obj + "<br>";
} else {
el.innerHTML += obj.lastEventId + " - " + obj.data + "<br>";
}
el.scrollTop += 20;
}
</script>
</head>
<body>
<h1>Server Sent Events ASP Example</h1>
<div id="notSupported">
Your browser does not support Server Sent Events.
Please use <a href="https://www.mozilla.org/firefox/new/">Firefox</a>
or <a href="https://www.google.com/chrome/browser">Google Chrome</a>.
</div>
<h2>Tickets</h2>
<div id="tickets">
<div class="ticket"><div class="name">IBM</div><div class="price" id="t_IBM">161.57</div></div>
<div class="ticket"><div class="name">AAPL</div><div class="price" id="t_AAPL">114.45</div></div>
<div class="ticket"><div class="name">GOOG</div><div class="price" id="t_GOOG">532.94</div></div>
<div class="ticket"><div class="name">MSFT</div><div class="price" id="t_MSFT">47.12</div></div>
</div>
<h2>Simple Log Console</h2>
<p class="hint">
This is simple log console. It is useful for testing purposes and to understand better how SSE works.
Event id and data are logged for each event.
</p>
<div id="log">
</div>
</body>
</html>
服务器发送事件ASP示例-股票票据
H1{
文本对齐:居中;
字体大小:150%;
边缘底部:60px;
}
氢{
文本对齐:居中;
字体大小:125%;
边缘底部:15px;
}
分区票{
利润率:10px自动80px自动;
}
分区票{
保证金:5px自动;
宽度:160px;
字体大小:115%;
}
部门名称{
显示:内联块;
宽度:80px;
填充:3倍;
}
分区价格{
显示:内联块;
宽度:60px;
填充:3倍;
文本对齐:右对齐;
过渡:所有0.2秒缓解;
}
DIV#log{
利润率:10px自动;
宽度:600px;
高度:200px;
背景:gainsboro;
填充物:5px;
溢出y:滚动;
}
DIV#不受支持{
显示:无;
利润率:10px自动;
文本对齐:居中;
颜色:红色;
字体大小:150%;
}
提示{
宽度:600px;
利润率:10px自动;
文本对齐:对齐;
文本缩进:20px;
线高:135%;
}
DIV#下载{
保证金:50px自动;
文本对齐:居中;
}
下载{
填充:10px 25px;
背景#F1592A;
颜色:白色;
文字装饰:无;
字体大小:20px;
边界半径:5px 5px;
}
下载A:悬停{
文字装饰:下划线;
背景#FF592A;
}
window.onload=函数setDataSource(){
如果(!!window.EventSource){
var source=新事件源(“stocks.asp”);
source.addEventListener(“消息”,函数(e){
更新价格(如数据);
日志信息(e);
},假);
source.addEventListener(“打开”,函数(e){
日志信息(“打开”);
},假);
source.addEventListener(“错误”,函数(e){
日志信息(“错误”);
if(e.readyState==EventSource.CLOSED){
日志信息(“已关闭”);
}
},假);
}否则{
document.getElementById(“不受支持”).style.display=“块”;
}
}
函数updatePrice(数据){
var ar=data.split(“:”);
var票据=ar[0];
var价格=应收账款[1];
var el=document.getElementById(“t_”+票证);
var oldPrice=el.innerHTML;
el.innerHTML=价格;
if(parseFloat(oldPrice)”;
}否则{
el.innerHTML+=obj.lastEventId+“-”+obj.data+“
”;
}
el.scrollTop+=20;
}
服务器发送事件ASP示例
您的浏览器不支持服务器发送的事件。
请使用
或
售票处
IBM161.57
AAPL114.45
GOOG532.94
MSFT47.12
简单日志控制台
这是一个简单的日志控制台。这对于测试目的和更好地理解SSE的工作原理非常有用。
记录每个事件的事件id和数据。
(请忽略OnEventListener而不是onmessage的使用——我可能没有说明最好的语法,但我不认为这是问题的原因)
这些来源是有效的,但非常古怪。例如,如果我不连续两次调用SendMessage,它将不起作用,而且服务器上似乎需要两个Response.flush语句。这是为什么
更重要的是,lastID应该如何处理。在PHP代码中,有一个叫做$\u SERVER\u LAST\u EVENT\u ID的东西。那是什么?是否有ASP的等价物?这有关系吗?我还没有尝试让事件ID根据SSE文档工作,这些文档显示了用于帮助断开连接的ID
关于这一点,我还有很多问题,但最重要的是,服务器上到底发生了什么?例如,如果我要建立一个到数据库的连接(MSSQL),以检查某个特定记录是否已被修改,并且有10个侦听器,这是否意味着有10个数据库连接,或者测试/事件流内容类型神奇地处理了这一问题?我在Remy Sharp的博客(html5doctor.com/server-sent-events/)中读到,“为了发布新事件,您需要维护一个所有连接用户的列表。”这是真的吗?事件流对象不是“自动”处理这个方面吗?你为什么要这么做