SSE及相关技术(web sockets, long polling等)

 

server-sent events--One Way Messaging

  

  


  

  允许网页获得来自服务器的更新,并且自动更新

  • Server-Sent Events: allow a web page to get updates from a server 
  • This was also possible before, but the web page would have to ask if any updates were available. With server-sent events, the updates come automatically.
  • Examples: Facebook/Twitter updates, stock price updates, news feeds, sport results, etc.

 

  原理如下:

  1. client利用regular http请求webpage
  2. 请求的webpage 执行javascript脚本,open a connection to server.
  3. 当有新的信息时服务器将信息发送给client

HTML5 SSE

 

 

 

浏览器支持情况:

 

desktop:

mobile:

 

 

使用入门:

 


 

receive Server-Sent Event Notifications: (接收Server-sent事件通知)

利用EventSource的onmessage获取消息

EventSource事件如下:

 

onopen   当服务器连接被打开时   When a connection to the server is opened

onmessage   当接收到消息       When a message is received

onerror

 


 

创建和关闭

var source = new EventSource();

source.close();

 

 


 数据格式:

data: My message\n\n

 如果数据比较长时,可以采用多行data:然后使用event.data.split('\n').join('')组合数据

data: first line\n
data: second line\n\n

 


 简单例子:

eg:html页面:

<!DOCTYPE html>
<html>
<head>
<style>
div{
    border-radius: 10px;
    border: 2px solid pink;
}
</style>
</head>
<body>
<h1></h1>
<div id="result"></div>

<script>
if(typeof(EventSource)!=="undefined")   //监测是否支持EventSource
  {
  var source=new EventSource("sseServer.jsp");
  source.onmessage=function(event)
    {
    document.getElementById("result").innerHTML+=event.data + "<br />";
    };
  }
else
  {
  document.getElementById("result").innerHTML="Sorry, your browser does not support server-sent events...";
  }
</script>

</body>
</html>

服务器sseServer.jsp代码:

<%@ page language="java" contentType="text/event-stream; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.util.Date"%>
<%@ page import="java.io.*"%>
<%
    Date date = new Date();
    System.out.println(date);
    response.setContentType("text/event-stream");      //设置contentType
    response.setHeader("Cache-Control", "no-cache");   //设置不缓存
    response.setHeader("Pragma","no-cache"); 
    response.setDateHeader("Expires",0);
    PrintWriter pw = response.getWriter();    
    pw.print("data: today is "+date.toString()+" wish you happy~~~");  //注意必须以data:开头
    pw.flush();
%>

结果:

 

 


 

eg2:传送多行数据:

if(typeof(EventSource)!=="undefined"){
  var source=new EventSource("multiLineServer.jsp");
  source.onmessage=function(event)
  {
        document.getElementById("result").innerHTML+=event.data.split('\n').join('') + "<br />";
  };
 
 }else{
  document.getElementById("result").innerHTML="Sorry, your browser does not support server-sent events...";
  }
    Date date = new Date();
    System.out.println(date);
    response.setContentType("text/event-stream");
    response.setHeader("Cache-Control", "no-cache");
    response.setHeader("Pragma","no-cache");
    response.setDateHeader("Expires",0);
    PrintWriter pw = response.getWriter();    
    pw.println("data: today is "+date.toString()+" wish you happy~~~");
    pw.println("data: have a nice day");
    pw.flush();

结果如下:

 


eg3:以json格式封装数据:

if(typeof(EventSource)!=="undefined"){
  var source=new EventSource("jsonServer.jsp");
  source.onmessage=function(event)
  {
      
      var data = JSON.parse(event.data);
      document.getElementById("result").innerHTML+="date:"+data.date + "<br />";
      document.getElementById("result").innerHTML+="name:"+data.name + "<br />";
  };
 
 }else{
  document.getElementById("result").innerHTML="Sorry, your browser does not support server-sent events...";
  }

server:

Date date = new Date();
System.out.println(date);
response.setContentType("text/event-stream");
response.setHeader("Cache-Control", "no-cache");
response.setHeader("Pragma","no-cache");
response.setDateHeader("Expires",0);
PrintWriter pw = response.getWriter();    
pw.println("data: {");
pw.println("data: \"date\":\""+date.toString()+"\",");
pw.println("data: \"name\":\"wish\"");
pw.println("data:}");
    
pw.flush();

 

结果如下:

 

 添加监听事件:

事件如下:

message

open

error

 

eg:

if(typeof(EventSource)!=="undefined"){
  var source=new EventSource("sseServer.jsp");
  source.addEventListener('message',function(event){
      //Connection was opended
        document.getElementById("result").innerHTML+=event.data + "<br />";

  },false);
 }else{
  document.getElementById("result").innerHTML="Sorry, your browser does not support server-sent events...";
  }

服务器端代码相同,结果与上例相同:

 

open和error事件如下:

source.addEventListener('open', function(event) {
  // Connection was opened.
}, false);

source.addEventListener('error', function(event) {
  if (event.readyState == EventSource.CLOSED) {
    // Connection was closed.
  }
}, false);

 注意:当连接关闭时,浏览器会自动在3秒后重新连接,可以在服务器端设置时间

 

 设置事件id和reconnect time

 


 

设置id

在stream前加上id:, 可以让浏览器跟踪最后一次触发的事件,如果服务器死掉时,可以在新的请求设置HTTP header,通过event.lastEventId可以获取该值

eg:

id: 1222\n
data: ...\n

 

 


 

设置reconnection time

默认是在连接关闭3秒后reconnect,可以通过设置stream更改

eg:设置5秒

retry: 50000\n
data: ......\n

 

自定义事件名称

 eg:设置update事件

stream:

event: update\n
data: {"username": "wish", "emotion": "happy"}\n

 

 js:

source.addEventListener('update', function(event) {
  var data = JSON.parse(event.data);
  console.log(data.username + ' is now ' + data.emotion);
}, false);

 

Security

在stream中增加origin

source.addEventListener('message', function(event) {
  if (event.origin != 'http://cnblogs.com') {
    //................
    return;
  }
  ...
}, false);

 其他请参考:Cross-document messaging security

 polling相关技术比较

 


Regular http:

  1. client发送请求.
  2. server计算
  3. server sends the response to the client.

HTTP

 

 


 

AJAX Polling:

  1. client利用regular http请求webpage
  2. 请求的webpage 执行javascript脚本以一定间隔向服务器请求file
  3. server计算每个reqponse,发送给client

AJAX Polling

 

 


AJAX Long-Polling:

  1. client利用regular http请求webpage
  2. 请求的webpage 执行javascript脚本向服务器请求file
  3. 服务器并不立即响应,而是等到有新的信息时才响应
  4. client收到response后立即发送新的请求,重复上面过程

AJAX Long-Polling

 

 


 

HTML5 Websockets:

  1. client利用regular http请求webpage
  2. 请求的webpage 执行javascript脚本,open a connection to server.
  3. 有新的信息时服务器和客户端可以相互发送信息(Real-time traffic from the server to the client and from the client to the server)

  4. 使用请查看:https://developer.mozilla.org/en-US/docs/WebSockets/Writing_WebSocket_client_applications

HTML5 WebSockets

 


Comet:

Comet 是HTML5技术之前使用streaming 和long-polling来实现实时应用程序的技术(Streaming and long polling for responsive communication between your server and client)更多了解 http://www.ibm.com/developerworks/web/library/wa-reverseajax1/index.html

Comet is a web application model where a request is sent to the server and kept alive for a long time, until a time-out or a server event occurs. When the request is completed, another long-lived Ajax request is sent to wait for other server events. With Comet, web servers can send the data to the client without having to explicitly request it. 

 

 

相关博文:HTML5 Web socket和socket.io

 

 

 

 参考:http://www.w3schools.com/html/html5_serversentevents.asp

    http://jaxenter.com/tutorial-jsf-2-and-html5-server-sent-events-42932.html

      http://www.html5rocks.com/en/tutorials/eventsource/basics/

      http://www.whatwg.org/specs/web-apps/current-work/multipage/comms.html#authors

      http://stackoverflow.com/questions/11077857/what-are-long-polling-websockets-server-sent-events-sse-and-comet

    http://www.ibm.com/developerworks/web/library/wa-reverseajax1/index.html

 

 

posted @ 2014-05-17 15:57  wishyouhappy  阅读(1888)  评论(2编辑  收藏  举报