服务器发送事件,服务器端代码

时间:2013-07-25 04:54:34

标签: php server-sent-events

实现服务器发送的事件是一项非常简单的任务。借用Mozilla文档中的示例,客户端代码将与

一致
var evtSource = new EventSource("ssedemo.php");
evtSource.onmessage = function(e){//do stuff with e.data here}

我理解的是服务器端发生了什么。困扰我的事情

  • 所以你想继续发送来自ssdemo.php的事件意味着你需要在循环中运行它并在它不发送时让它休眠
  • 但默认情况下,Apache设置为杀死执行“太长”的脚本,因此除非您设置该脚本以此方式运行,否则这不能是无限循环
  • 如果我有10个用户请求相同的SSE服务(ssdemo.php),那么它是否意味着我将拥有该循环脚本的10个实例?

我怀疑我对服务器端代码如何工作的理解应该是有缺陷的或天真的或两者兼而有之。我非常感谢任何指向正确方法的指示。

2 个答案:

答案 0 :(得分:1)

您的理解是正确的。 PHP需要继续运行,在PHP中你需要一个循环,你将很快耗尽免费的Apache线程。

如果您需要处理大量连接,则需要使用基于事件的服务器,如Node.js或Tornado,它们可以处理大量的开放连接。

如果您更愿意使用PHP,那么部分解决方案是在几秒钟后关闭连接。浏览器将重新连接,因此您将获得轮询和SSE的混合。

在PHP中,您可以检查sys_getloadavg()以确定是否可以保持连接打开,或者您的免费流程是否正常运行。

答案 1 :(得分:0)

在SSE方面,我一直在寻找同样的问题,这是我的研究:

我有一个基本的javax HttpServlet,它会在每个rando秒将数据打印到PrintWriter。

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException {
  System.out.println("You just entered the doGetMethod");
  response.setContentType("text/event-stream");
  response.setCharacterEncoding("UTF-8");
  PrintWriter printWriter = null;
  while(true){
    try{
      System.out.println("You just entered the while loop");
      double randomNumber = Math.random()*10000;
      printWriter = response.getWriter();
      printWriter.print("data: " + "[next server time check event in " +
      Math.round(randomNumber/1000) + " seconds]\n");
      printWriter.print("data: " + "Time: " + Calendar.getInstance().getTime() + "\n\n");
      response.flushBuffer();
      Thread.sleep((long)randomNumber);

    } catch (IOException | InterruptedException e){
      e.printStackTrace();
      break;
    }
  }
  System.out.println("Connection was aborted");
}

这是填充{textarea id =" displayTextArea}元素的脚本

<script>
  var eventSource = null;
  function start(){
    eventSource = new EventSource('http://localhost:8080/SSEServlet');
    eventSource.onopen = function(){displayTextArea.value+='Connected ..' + '\n';};
    eventSource.onmessage = function(message){displayTextArea.value+=message.data + '\n\n';};
    eventSource.onerror = function(){displayTextArea.value+='Error Occurred...' + '\n';};
  }
  function stop(){
    eventSource.close();
  }
  function clearText(){
    displayTextArea.value = '';
  }
</script>

- 回答您的第一个问题
 如果您在运行应用程序时观察控制台,您会注意到控制台无法打印&#34;您刚刚输入了doGetMethod&#34;直到您向servlet路径发送HTTP GET请求。这证实了在有人调用servlet之前不会创建Servlet实例和req / resp对象的理解。 How do servlets work?
- 第二和第三个问题:
 默认情况下,Tomcat将为每个连接分配一个线程(Source)。在我目前的配置中,我的程序将最多连接6个。每个连接都将创建自己的servlet实例,并且在连接打开时,将保持while循环。当我运行服务器并打开单独的连接,查看不同的时间和随机间隔的顺序时,就证明了这一点。我的while循环不是无限的尽管它等待直到连接关闭然后抛出异常并打破while循环。连接关闭后,servlet将关闭。

我这样做是非常业余的做SSE的方式。如果你想为此学习高级图书馆,我会查看jeaSSE

如果有人想要完整的code

相关问题