HTML5中的服务器‘推送’技术一 web服务器推送技术

一直以来,HTTP协议都是严格遵循Request-Response模型的。客户端发送一个Request到服务器,服务器对Request作出响应并将Response发送回客户端。也就是说,所有的互动都是由客户端发起的,服务器不会发起任何互动。

为了创建互动性更强的web应用程序,AJAX出现了,AJAX实现了一个动态的从Server获取数据的方法。通过使用AJAX,浏览器通过XMLHttpRequestAPI来发送HTTP request。XMLHttpRequest使得我们可以在不阻塞用户界面的情况下向服务器发送异步的HTTPrequest来获取数据。但是AJAX并没有定义新的HTTP request类型,只是将发送HTTPrequest的工作移到了后台,不影响用户的操作。因此AJAX也没有打破Request-Response的模型,还是由浏览器从服务器‘拉’数据。

另外一种技术是Comet,也称为反向Ajax。和Ajax一样,Comet也是建立在已经存在的HTTP协议之上的。Comet会维护一个长期存活的HTTP连接,发送‘假’的请求从而得到response。

这些都是为了打破HTTP协议的限制的解决方法。但是在HTML5中,这种限制会被打破。HTML5规范中包含很多功能强大的特性,能够将浏览器变成功能齐全的RIA客户端平台。Server-SentEvent和WebSockets就是其中的两个特性,这两个特性能够帮助我们实现服务器将数据‘推送’到客户端的功能。

在这篇文章中我们先介绍一下Server-SentEvents特性
Server-Sent Events

Server-Sent Events实际上将Comet技术进行了标准化。Server-Sent Events规范“定义了API来打开一个HTTP连接,通过该连接能够获取从服务器推送的通知”。Server-Sent Events包含新的HTML元素EventSource和新的MIME类型text/event-stream,这个MIME类型定义了事件框架格式。

1.<html>

2.<head>

3.<scripttype='text/javascript'>

4.var source =new EventSource('Events');

5.source.onmessage= function (event) {

6.ev =document.getElementByIdx_x_x_x('events');

7.ev.innerHTML+= "<br>[in] " +event.data;

8.};

9.</script>

10. </head>

11. <body>

12. <divid="events"></div>

13. </body>

14. </html>

EventSource代表的是接收事件的客户端的终点。客户端通过创建EventSource对象来打开一个event stream。创建EventSource对象时,该对象接收一个事件来源的URL作为其构造函数的参数。当每次收到新的事件数据时onmessage事件处理器会被调用。

通常情况下,浏览器会限制到每个服务器的连接的数量。在有些情况下,装载多个包含到同一个域的EventSource对象的页面会导致对每个EventSource创建一个专属于该EventSource的连接,这种情况下很快就会超出连接数量限制。为了处理这种情况,我们可以使用共享的WebWorker,该对象共享一个EventSource的实例。另外,通过定义浏览器特定的EventSource实现,我们可以做到如果两个EventSource的URL是相同的,那么他们就重用相同的连接。这时,共享的连接就由浏览器特定的EventSource实现来管理。

当event stream打开的时候,浏览器会发送如下的HTTP request。

REQUEST:

1.GET /Events HTTP/1.1

2.Host: myServer:8875

3.User-Agent: Mozilla/5.0 (Windows; U; Windows NT5.1; de-DE)

4.AppleWebKit/532+(KHTML, like Gecko)Version/4.0.4

5.Safari/531.21.10

6.Accept-Encoding: gzip, deflate

7.Referer: http://myServer:8875/

8.Accept: text/event-stream

9.Last-Event-Id: 6

10. Accept-Language: de-DE

11. Cache-Control: no-cache

12. Connection: keep-alive

Accept定义了需要的格式text/event-stream。虽然Server-Sent Events规范定义了text/event-stream的MIME 类型,该规范同时允许使用其他的事件框架格式。但是Server-Sent Events的实现必须支持test/event-stream格式。
HTML5中的服务器‘推送’技术(一) web服务器推送技术
根据text/event-stream的格式,一个事件有一个或多个注释行和字段行组成。注释行是由冒号:开始的行。字段域行由字段名和字段值组成,字段名和字段值也是由冒号:分隔。多个事件之间用空行分隔。下面就是一个Response的例子:
RESPONSE:

1.HTTP/1.1 200 OK

2.Server:xLightweb/2.12-HTML5Preview6

3.Content-Type: text/event-stream

4.Expires: Fri, 01 Jan 1990 00:00:00GMT

5.Cache-Control: no-cache, no-store, max-age=0,must-revalidate

6.Pragma: no-cache

7.Connection: close

8.

9.: time stream

10. retry: 5000

11.

12. id: 7

13. data: Thu Mar 11 07:31:30 CET2010

14.

15. id: 8

16. data: Thu Mar 11 07:31:35 CET2010

17.

18. [...]

根据定义,Event stream不应该被缓存。为了避免缓存,在Response的头中包含了Cache-Control,禁止了缓存该response。

上面的例子中,该response中包含三个事件。第一个事件包含一个注释行和一个retry字段;第二个事件和第三个事件都是包含一个id字段和一个data字段。data字段中包含的是事件的数据,在上面的例子中是当前的时间。id字段是用来在event stream中跟踪处理进程的。上面的例子中,服务器端的应用程序会每隔5秒向event stream中写入一个事件。当EventSource接收到该事件后,onmessage事件处理器就会被调用。

不同的是,第一个事件不会触发onmessage处理器。第一个个事件没有data字段,只包含一个注释行和一个retry字段,retry字段是用于重新连接的目的的。retry字段定义了重新连接的时间,单位是毫秒。如果收到了这样的字段,EventSource会更新其相关的重新连接时间的属性。在发生网络错误的情况下,重新连接时间在提高可靠性方面扮演了重要的角色。当EventSource实例发现连接断开了,在指定的重新连接时间之后会自动的重建连接。

我们可以看到,在HTTP request中,我们可以指定Last-Event-Id。EventSource在重建连接的时候会指定该值。每次EventSource收到包含id字段的事件时,EventSource的last event id属性会被更改,在重建连接的时候,EventSource的last event id属性会被写入HTTP request的Last-Event-Id中。这样如果服务器端实现了lastEventId的处理,就可以保证在重建的连接中不会发送已经收到的事件了。

下面的代码是一个基于Java HTTP 库xLightweb(包含HTML5预览扩展)的HttpServer的例子。

1.class ServerHandler implements IHttpRequestHandler{

2.private finalTimer timer = new Timer(false);

3.public voidonRequest(IHttpExchange exchange) throws IOException{

4. StringrequestURI =exchange.getRequest().getRequestURI();

5. if(requestURI.equals("/ServerSentEventExample")) {

6.sendServerSendPage(exchange,requestURI);

7. } else if(requestURI.equals("/Events")) {

8.sendEventStream(exchange);

9. } else{

10. exchange.sendError(404);

11. }

12. }

13. private voidsendServerSendPage(IHttpExchangeexchange,

14. String uri)throws IOException {

15. String page= "<html>rn " +

16. "<head>rn" +

17. "<scripttype='text/javascript'>rn" +

18. "var source =new EventSource('Events');rn" +

19. "source.onmessage= function (event) {rn" +

20. " ev =document.getElementByIdx_x_x_x('events');rn" +

21. " ev.innerHTML += "<br>[in] " +event.data;rn"+

22. "};rn"+

23. "</script>rn"+

24. "</head>rn" +

25. "<body>rn" +

26. " <divid="events"></div>rn"+

27. "</body>rn" +

28. "</html>rn";

29. exchange.send(new HttpResponse(200, "text/html",page));

30. }

31. private voidsendEventStream(final IHttpExchangeexchange)

32. throwsIOException {

33. // get thelast id string

34. final StringidString = exchange.getRequest().getHeader(

35. "Last-Event-Id", "0");

36. // sendingthe response header

37. finalBodyDataSink sink =exchange.send(new

38. HttpResponseHeader(200,"text/event-stream"));

39. TimerTask tt= new TimerTask() {

40. private intid = Integer.parseInt(idString);

41. public voidrun() {

42. try{

43. Event event =new Event(new Date().toString(), ++id);

44. sink.write(event.toString());

45. } catch(IOException ioe) {

46. cancel();

47. sink.destroy();

48. }

49. };

50. };

51. Event event= new Event();

52. event.setRetryMillis(5 * 1000);

53. event.setComment("time stream");

54. sink.write(event.toString());

55. timer.schedule(tt, 3000, 3000);

56. }

57. }

58. XHttpServer server = new XHttpServer(8875, newServerHandler());

59. server.start();

Server-Sent Events规范推荐如果没有其他的数据要发送,那么定期的发送keep-alive注释。这样代理服务器就可以在某个HTTP连接有一段时间不活跃时关闭该连接,这样代理服务器能够关闭空闲的连接来避免浪费连接在没有响应的HTTP服务器上。发送注释事件使得这种机制不会发生在有效的连接上。尽管EventSource会自动重建连接,但是发送注释事件还是能够避免不必要的重新连接。

Server-Sent Event是基于HTTP streaming的。如上所述,response会一直打开,当服务器端有事件发生的时候,事件会被写入response中。理论上来说,如果网络的中介如HTTP代理不立即转发部分的response,HTTP streaming会导致一些问题。现在的HTTP RFC (RFC2616 Hypertext Transfer Pro tocal –HTTP/1.1)没有要求部分的response必须被立刻转发。但是,很多已经存在的流行的、工作良好的web应用程序是基于HTTP streaming的。而且,产品级别的中介通常会避免缓冲大量的数据来降低内存的占用率。

和其他的流行的Coment协议如Bayeux和BOSH不同,Server-Sent Event只支持单向的从服务器到客户端的通道。Bayeux协议支持双向的通信通道。另外,Bayeux能够使用HTTP Streaming和轮询。BOSH协议也支持双向通信通道,但是BOSH是基于轮询机制的。(所谓的轮询就是客户端定期发送request到服务器端来获取数据)。

尽管Server-Sent Events比Bayeux和BOSH的功能要少,但是在只需要单向的服务器向客户端推送数据的情况下(在很多情况下都是这样),Server-Sent Events有潜力成为占主导地位的协议。Server-Sent Events协议被Bayeus和BOSH要简单的多。另外,Server-Sent Events被所有兼容HTML5的浏览器支持(这就是规范的威力啊)。

  

爱华网本文地址 » http://www.413yy.cn/a/25101016/307678.html

更多阅读

足球实战中的十大射门技术技巧 射门用哪个部位

足球实战中的十大射门技术技巧——简介射门是运动员在比赛中的技术、身体素质、意识和心里素质的综合体现。提高射门技术水平,无论对业余爱好者还是专业球员来说都起着巨大的帮助作用。下面小编就和大家分享一下,实战足球当中的几大射

截图 《SchoolDays》·游戏中的三个主要结局一 school days结局视频

不要急着往下翻,先听我说……  之所以说是主要结局,我在网上查了一下,据说游戏多达20几种结局……我已知道的结局有12个,但是除了主要结局,几乎都是在游戏进行到中途时就FIN了,而这三个主要结局是要将游戏进行到最后才能达成的。  另

又见一帘幽梦中的经典台词 又见一帘幽梦第二部

1、云帆:计划赶不上变化,变化赶不上电话,电话赶不上一句话。2、紫菱:照片是一种记录,记录着我曾经拥有过什么,经历过什么,等我们老的时候也能回忆些什么。3、云帆:其实我们常常都会有这种类似的感觉,某个地方我们好象来过,某个陌生人我们好象

声明:《HTML5中的服务器‘推送’技术一 web服务器推送技术》为网友娶你可好分享!如侵犯到您的合法权益请联系我们删除