浏览器中未触发JavaScript EventSource SSE

浏览器中未触发JavaScript EventSource SSE,javascript,html,node.js,server-sent-events,Javascript,Html,Node.js,Server Sent Events,我一直在开发一个nodejs服务器,为我用HTML5开发的新网站提供服务器端事件 当我将telnet发送到服务器时,它可以正常工作,向我发送所需的HTTP响应头,然后发送我当前每2或3秒生成的事件流,以证明它可以正常工作 我尝试了最新版本的FireFox、Chrome和Opera,他们创建了EventSource对象并连接到nodejs服务器,但没有浏览器生成任何事件,包括onopen、onmessage和onerror 但是,如果我停止nodejs服务器,终止浏览器的连接,它们都会突然发送所有

我一直在开发一个nodejs服务器,为我用HTML5开发的新网站提供服务器端事件

当我将telnet发送到服务器时,它可以正常工作,向我发送所需的HTTP响应头,然后发送我当前每2或3秒生成的事件流,以证明它可以正常工作

我尝试了最新版本的FireFox、Chrome和Opera,他们创建了EventSource对象并连接到nodejs服务器,但没有浏览器生成任何事件,包括onopen、onmessage和onerror

但是,如果我停止nodejs服务器,终止浏览器的连接,它们都会突然发送所有消息,并显示我的所有事件。然后所有浏览器都尝试按照规范重新连接到服务器

我在网络服务器上托管所有内容。本地文件中没有运行任何内容

我已经阅读了所有我能在网上找到的东西,包括我买的书,没有任何迹象表明有任何这样的问题。我有什么遗漏吗

示例服务器实现

  var http = require('http');
  var requests = [];

  var server = http.Server(function(req, res) {
    var clientIP = req.socket.remoteAddress;
    var clientPort = req.socket.remotePort;

    res.on('close', function() {
      console.log("client " + clientIP + ":" + clientPort + " died");

      for(var i=requests.length -1; i>=0; i--) {
        if ((requests[i].ip == clientIP) && (requests[i].port == clientPort)) {
          requests.splice(i, 1);
        }
      }
    });

    res.writeHead(200, {
      'Content-Type': 'text/event-stream', 
      'Access-Control-Allow-Origin': '*', 
      'Cache-Control': 'no-cache', 
      'Connection': 'keep-alive'});

    requests.push({ip:clientIP, port:clientPort, res:res});

    res.write(": connected.\n\n");
  });

  server.listen(8080);

  setInterval(function test() {
    broadcast('poll', "test message");
  }, 2000);

function broadcast(rtype, msg) {
  var lines = msg.split("\n");

  for(var i=requests.length -1; i>=0; i--) {
    requests[i].res.write("event: " + rtype + "\n");
    for(var j=0; j<lines.length; j++) {
      if (lines[j]) {
        requests[i].res.write("data: " + lines[j] + "\n");
      }
    }
    requests[i].res.write("\n");
  }
}
var http=require('http');
var请求=[];
var server=http.server(函数(req,res){
var clientIP=req.socket.remoteAddress;
var clientPort=req.socket.remotePort;
res.on('close',function(){
log(“客户端”+clientIP+:“+clientPort+”已死亡”);
对于(var i=requests.length-1;i>=0;i--){
if((请求[i].ip==clientIP)和&(请求[i].port==clientPort)){
请求。拼接(i,1);
}
}
});
文书标题(200{
“内容类型”:“文本/事件流”,
“访问控制允许来源”:“*”,
“缓存控制”:“无缓存”,
“连接”:“保持活动状态”});
push({ip:clientIP,port:clientPort,res:res});
res.write(“:已连接。\n\n”);
});
监听服务器(8080);
setInterval(函数测试(){
广播(“轮询”、“测试消息”);
}, 2000);
功能广播(rtype,msg){
变量行=msg.split(“\n”);
对于(var i=requests.length-1;i>=0;i--){
请求[i].res.write(“事件:+rtype+”\n”);
对于(var j=0;j

因为为这些资源建立到远程服务器的连接是 预计寿命较长,UAs应确保 使用缓冲。特别是,使用行进行行缓冲时 定义为以单个U+000A换行符(LF)结束是安全的, 具有不同预期行结尾的块缓冲或行缓冲 可能导致事件调度延迟

尝试使用行尾(
“\r\n”
,而不是
“\n”

作者还注意到HTTP分块可能会产生意外的结果 对本协议可靠性的负面影响。如果可能, 应为服务事件流禁用分块,除非速率 消息的数量足够高,这无关紧要

破解它!:)

多亏了帮助我进行测试的人的帮助。结果证明代码不是问题所在

警告..如果您的客户端使用任何类型的防病毒软件拦截web请求,可能会在此处引发问题。在这种情况下,Sophos Endpoint Security(提供企业级防病毒和防火墙保护)具有一种称为web保护的功能。在该功能中,有一个选项可以扫描下载;似乎SSE connection被视为下载,因此在关闭连接并接收到要扫描的流之前不会发布到浏览器。禁用此选项可以解决问题。我已提交错误报告,但其他防病毒系统也可能会这样做


感谢您的建议和帮助:)

我修改了您的服务器端脚本,“似乎”对Chrome部分有效。
但每2次广播的连接中断&客户端上只能显示1次

Firefox适用于第一次广播,并通过以下错误停止:

错误:加载页面时,与/sse的连接被中断

Chrome将尝试重新连接并接收第三次广播

我认为这也与防火墙设置有关,但无法解释为什么有时会起作用

注意:对于响应的事件侦听器(第10行),“关闭”和“结束”有不同的结果,
您可以尝试一下,我的结果是[close:1 success/2 broadcast]&[end:1 success/8 broadcast]

var http = require('http'), fs = require('fs'), requests = [];

var server = http.Server(function(req, res) {
  var clientIP = req.socket.remoteAddress;
  var clientPort = req.socket.remotePort;
  if (req.url == '/sse') {
    var allClient="";for(var i=0;i<requests.length;i++){allClient+=requests[i].ip+":"+requests[i].port+";";}
    if(allClient.indexOf(clientIP+":"+clientPort)<0){
      requests.push({ip:clientIP, port:clientPort, res:res});
      res.on('close', function() {
        console.log("client " + clientIP + ":" + clientPort + " died");
        for(var i=requests.length -1; i>=0; i--) {
          if ((requests[i].ip == clientIP) && (requests[i].port == clientPort)) {
            requests.splice(i, 1);
          }
        }
      });
    }
  }else{
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write(fs.readFileSync('./test.html'));
    res.end();
  }
});
server.listen(80);

setInterval(function test() {
  broadcast('poll', "test message");
}, 500);

var broadcastCount=0;
 function broadcast(rtype, msg) {
    if(!requests.length)return;
    broadcastCount++;
    var lines = msg.split("\n");
    for(var i = requests.length - 1; i >= 0; i--) {
        requests[i].res.writeHead(200, {
            'Content-Type': 'text/event-stream',
            'Cache-Control': 'no-cache',
            'Connection': 'keep-alive'
        });
        requests[i].res.write("event: " + rtype + "\n");
        for(var j = 0; j < lines.length; j++) {
            if(lines[j]) {
                requests[i].res.write("data: " + lines[j] + "\n");
            }
        }
        requests[i].res.write("data: Count\: " + broadcastCount + "\n");
        requests[i].res.write("\n");
    }
    console.log("Broadcasted " + broadcastCount + " times to " + requests.length + " user(s).");
 }
var http=require('http')、fs=require('fs')、requests=[];
var server=http.server(函数(req,res){
var clientIP=req.socket.remoteAddress;
var clientPort=req.socket.remotePort;
如果(req.url='/sse'){
var allClient=“”;for(var i=0;i=0;i--){
请求[i].res.writeHead(200{
“内容类型”:“文本/事件流”,
“缓存控制”:“无缓存”,
“连接”:“保持活动”
});
请求[i].res.write(“事件:+rtype+”\n”);
对于(var j=0;j
使用了各种浏览器的Javascript控制台后,EventSource似乎会向我的服务器发出GET/sse HTTP/1.1,这是预期的,但在连接关闭之前不会显示响应。这是设计上的吗?连接状态应该保持活动状态。EventSource()是吗只是缓冲它发送的所有内容,直到页面关闭,或者它正在等待它接收的数据中的某种标记?除了nodejs服务器,我还尝试了PHP,因为很多例子似乎都说明了这一点。同样,除非我关闭连接,否则这会表现出与前面提到的相同的行为。我很惊讶没有其他人使用PHP广告问题
var http = require('http'), fs = require('fs'), requests = [];

var server = http.Server(function(req, res) {
  var clientIP = req.socket.remoteAddress;
  var clientPort = req.socket.remotePort;
  if (req.url == '/sse') {
    var allClient="";for(var i=0;i<requests.length;i++){allClient+=requests[i].ip+":"+requests[i].port+";";}
    if(allClient.indexOf(clientIP+":"+clientPort)<0){
      requests.push({ip:clientIP, port:clientPort, res:res});
      res.on('close', function() {
        console.log("client " + clientIP + ":" + clientPort + " died");
        for(var i=requests.length -1; i>=0; i--) {
          if ((requests[i].ip == clientIP) && (requests[i].port == clientPort)) {
            requests.splice(i, 1);
          }
        }
      });
    }
  }else{
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write(fs.readFileSync('./test.html'));
    res.end();
  }
});
server.listen(80);

setInterval(function test() {
  broadcast('poll', "test message");
}, 500);

var broadcastCount=0;
 function broadcast(rtype, msg) {
    if(!requests.length)return;
    broadcastCount++;
    var lines = msg.split("\n");
    for(var i = requests.length - 1; i >= 0; i--) {
        requests[i].res.writeHead(200, {
            'Content-Type': 'text/event-stream',
            'Cache-Control': 'no-cache',
            'Connection': 'keep-alive'
        });
        requests[i].res.write("event: " + rtype + "\n");
        for(var j = 0; j < lines.length; j++) {
            if(lines[j]) {
                requests[i].res.write("data: " + lines[j] + "\n");
            }
        }
        requests[i].res.write("data: Count\: " + broadcastCount + "\n");
        requests[i].res.write("\n");
    }
    console.log("Broadcasted " + broadcastCount + " times to " + requests.length + " user(s).");
 }