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

如何解决使用经典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 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-