使用经典ASP的服务器发送事件SSE:实现LastEventID并支持多个侦听器

问题描述

显然,由于Internet Explorer从未支持服务器发送的事件,因此几乎没有为经典ASP编写的示例。大多数已发布的示例都使用NodeJS或PHP,但是此网站上的文章以及其他文章指出或暗示可以使用任何中间件语言。

我已经获得了使用ASP的准系统代码(使用VBS),但实际上我不明白两件事:如何将最新的EventID成功发送到特定的侦听器,以及我的代码需要达到什么程度(如果有)跟踪当前侦听器的列表。全面披露-我对这种代码没有太多的“感觉”。例如,我花了一段时间才意识到,从服务器发送的“消息”只是使用Response.Write将语法用于常规文本输出

好的,在我问两个问题之前,这是我正在使用的代码。这取自我发现的PHP示例(http://www.howopensource.com/2014/12/introduction-to-server-sent-events/)。它从正在读取的数组中输出值(看起来就像股票价格数据一样)。在PHP示例中,sleep()函数用于在事件之间设置延迟。代替ASP,我在注释中使用了建议给我的另一种技术(请参阅下文),产生了大约3秒的同步延迟。 因此,这是服务器端的ASP代码

<%@ 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),1)
        sendMessage lastId+1,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,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>

(请忽略OnEventListener的使用,而不是onmessage的使用-我可能没有说明最佳语法,但我认为这不是造成问题的原因)。

这些资源有效,但是非常古怪。例如,如果我没有连续两次调用SendMessage,它将无法正常工作,并且在服务器上似乎两个Response.flush语句都是必需的。为什么会这样?

更重要的是,lastID应该如何处理。在PHP代码中,有一个叫做$ _SERVER_LAST_EVENT_ID的东西。那是什么?是否有ASP的等效项?有关系吗?我尚未尝试根据SSE文档使事件ID正常工作,该事件ID显示了用于帮助断开连接的ID。

我对此确实有很多疑问,但是最重要的是,服务器上到底发生了什么?例如,如果我要建立与数据库(MSsql)的连接以检查特定记录是否已被修改,并且有10个侦听器,这意味着10个数据库连接,还是测试/事件流内容神奇地类型化照顾这个?我在雷米·夏普(Remy Sharp)的博客(html5doctor.com/server-sent-events/)中读到:“您需要维护所有已连接用户的列表才能发出新事件。”这是真的吗?事件流对象是否可以“自动”处理此方面?为什么雷米·夏普(Remy Sharp)会写“理想情况下,您应该使用具有事件循环的服务器。这意味着您不应使用Apache,而应使用诸如Node.js之类的平台...”这是什么意思?使用While True无限循环是否完全错误

还有很多我不了解的事情(重新连接等),但只允许我再问一个问题:我读过(https://medium.com/conectric-networks/a-look-at-server-sent-events-54a77f8d6ff7#:~:text=When%20working%20with%20Server%20Sent,stream%20of%20events%20over%20time.)浏览器仅限于6个SSE连接,例如,指向此.htm文件的六个标签,称为.asp文件。但是,当我尝试时,一次只能获得一个标签。如果我打开第二个选项卡,则第一个选项卡显示错误,然后第二个选项卡开始工作。只有打开两个不同的浏览器(例如firefox和chrome),我才能显示两个同时处理该窗口的窗口。我的应用程序所在的环境中,用户通常会在单个浏览器的多个选项卡中查看这些事件。我知道这适用于原始的PHP示例。为什么我的ASP代码不这样做?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)