在种种BS架构的应用程序中,往往都希望服务端能够自动地向客户端推送种种新闻,以到达类似于邮件、新闻、待办事项等通知。
往BS架构自己存在的问题就是,服务器一直接纳的是一问一答的机制。这就意味着若是客户端不自动地向服务器发送新闻,服务器就无法得知若何给客户端推送新闻。
随着HTML、浏览器等各项手艺、尺度的生长,依次天生了差别的手段与方式能够实现服务端自动推送新闻,它们分别是:AJAX,Comet,ServerSent以及WebSocket。
本篇文章将对上述提及到的种种手艺手段举行直白化的注释。
正常的一个页面在浏览器中是这样事情的:
此时,用户点击了网站上任何一个<a>或触发任何一个<form>提交时:
我们不难发现的是整个历程中心,一旦确立了一个毗邻,页面就无法再维护住了。整个历程看上去有点强买强卖,也许我只要一杯新的可乐,但你非要给我一整个套餐组合。
此时我们可以领会一下XmlHttpRequest组件,这个组件提供我们手动确立一个HTTP请求,发送我们想要的数据,服务器也可以只返回我们想要的效果,最大的利益是,当我们收到服务器的响应时,原来的页面没有被摧毁。这就好比,我喊一句"我的咖啡喝完了,我要续杯",然后服务员就拿了一杯咖啡过来,而不是会把我没吃完的套餐所有倒掉。
当我们行使AJAX实现服务器推送时,实在质是客户端不停地向服务器询问"有没有给我的新闻呀?",然后服务器回覆"有"或"没有"来到达的实现效果。它的实现方式也很简朴,行使jQuery框架封装好的AJAX挪用也很利便:
function getMessage(fn) { $.ajax({ url: "Handler.ashx", //一个能够提供新闻的页面 dataType: "text", //响应类型,可以是JSON,XML等其它类型 type: "get", //HTTP请求类型,还可以是post success: function (d, s) { fn(d); //得到了正常的响应时,行使回调函数通知外部 }, complete: function (x, s) { setTimeout(function () { getMessage(fn); }, 5000); //无论响应乐成或失败,在若干秒后再询问一次服务器 } }); }
通过上面的代码,可以每隔5秒询问一次服务器是否有需要处置的新闻,通过这种方式可以到达推送的效果,然则会存在一个问题:
而且严格地来说,这种现实方式,并不是真正意义上的服务器自动推送新闻,但由于早期手艺手段缺乏,以是AJAX轮循成为了一种很普遍的手段。
我们知道HTTP请求实在是基于TCP毗邻实现的,再看看之前说的HTTP请求处置历程:
看到这个处置历程,我们不难联想到,若是把第4步——关闭毗邻给省掉,那不就相当于有一个长毗邻一直被维持住了么。通过对服务端的一些操作,我们可以直接将数据从这个TCP毗邻发送客户端了。
通过这种手艺,我们可以大大提高服务器推送的实时性,还可以减去服务端不停地确立、施放毗邻所形成的开销。
现在市面上有不少基于AJAX实现的Comet机制,但主要有两种方式:
Server-Sent是HTML5提出一个尺度,它延用了Comet的思绪,并对其举行了一些规范。使得Comet这项手艺由原来的分支衍生手艺转成了正统的官方尺度。
它的原理与Comet相同,由客户端提议与服务器之间确立TCP毗邻,然后并维持这个毗邻,至到客户端或服务器中的做任何一放断开,ServerSent使用的是"问"+"答"的机制,毗邻确立后浏览器会周期性地发送新闻至服务器询问,是否有自己的新闻。
这项尺度不仅要求了支持的浏览器能够原生态的确立与服务器的长毗邻,更要求了对JavaScript剧本的统一性,使得兼程该功效的浏览器可以使用统一套代码完成Server-Sent的编码事情。
确立代码异常简朴:
//界说一个ServerSent工具 var s = new EventSource("Handler.ashx"); //当收到一个非自界说事宜时的回调函数 s.onmessage = function (e) { alert(e.data); }; //当收到一个被服务器命名为MyEvent事宜新闻时的回调函数 s.addEventListener("MyEvent", function (e) { alert(e.data); });
而服务器的代码也很简朴:
public class Handler : IHttpHandler { public void ProcessRequest(HttpContext context) { context.Response.ContentType = "text/event-stream"; context.Response.Expires = -1; context.Response.Write("event: MyEvent\r\n"); //事宜类型,使用\r\n末端 context.Response.Write("data: HelloWorld!\r\n"); //事宜数据,换行时使用\r\n,并在新行再加上data: context.Response.Write("data: I'm server!\n\n"); //事宜数据竣事,使用\n\n context.Response.Flush(); //这里不能用End,否则是关闭毗邻的 } public bool IsReusable { get { return true; } } }
两小段代码,就已经具备了服务器新闻推送了。
总得来说SeverSent就是HTML5规范下的Comet,具有更好的统一性,而且简朴好用。
看名字就知道了,这是一个可以用在浏览器上的Socket毗邻。
这也是一个HTML5尺度中的一项内容,他要求浏览器可以通过JavaScript剧本手动确立一个TCP毗邻与服务端举行通讯。
WebSocket不包罗太多的分外功效,仅仅就是TCP毗邻的几项基本功效:确立,暂且以及发送。
另外WebSocket使用了ws和wss协议,需要服务器有与之握手的算法才气将毗邻打开。
以是WebSocket相对于之前几种手段来说,其编码量是最大的,但由于没有其它的约束,因此它也可以自由地实现所有可能的功效。
即可以知足"问"+"答"的响应机制,也可以实现自动推送的功效。
与ServerSent相同,HTML5也对WebSocket挪用的JavaScript举行规范,我们可以弄过很简朴的一代码构建一个WebSocket毗邻
var ws = new WebSocket("ws://192.168.0.105:10080"); //毗邻服务器 ws.onopen = function (event) { alert("已经与服务器确立了毗邻\r\n当前毗邻状态:" + this.readyState); }; ws.onmessage = function (event) { alert("接收到服务器发送的数据:\r\n" + event.data); }; ws.onclose = function (event) { alert("已经与服务器断开毗邻\r\n当前毗邻状态:" + this.readyState); }; ws.onerror = function (event) { alert("WebSocket异常!"); };
还可以通过send的方式发送新闻
ws.send("Hello World");
WebSocket具有较为庞大的协议,需要在服务端做分外编程才气举行数据通讯。有关协议的详细内容,我会在以后的文章中举行注释。
MessageQueue,简称MQ,也就是新闻排队。是一种经常用于Tcp服务端的手艺。通过生产和接见种种新闻类型,MQ服务器会将生产者所天生的新闻发给感兴趣的客户端。市面上有许多的MQ框架,好比:ActiveMQ。
ActiveMQ已经支持了WebSocket协议,也就意味着,WebSocket已经可以作为一个生产者或一个消费者,与MQ服务器毗邻。
开发者可以通过MQTT的JS剧本,毗邻上MQ服务器,同时将Web服务器也连上MQ服务器,今后可以告别了Http通讯协议,完完全全使用Socket通讯来完成数据的交流。
总得来说,在HTML5规范下,最推荐使用ServerSent和WebSocket的方式举行服务器新闻的推送。
对比这两种方式。
ServerSent的方式,可以使服务端的开发依然依用以前的方式,然则其事情方式与Comet类似。
而WebSocket的方式,则对服务端的开发有着较高的要求,但其事情方式是完全的推送。
我本人实在挺偏向WebSocket + MQ的事情方式,然则对于老项目的翻新,照样用SeverSent比较好
本文为作者原创,转载请注明出处:http://www.cnblogs.com/ShimizuShiori/p/5464063.html
文章中的相关代码可以在 http://j.zizhusoft.com/Develop/Explorer.aspx 中的ServerSent目录中查看
1.阿里云: 本站现在使用的是阿里云主机,平安/可靠/稳固。点击领取2000米代金券、领会最新阿里云产物的种种优惠流动点击进入
2.腾讯云: 提供云服务器、云数据库、云存储、视频与CDN、域名等服务。腾讯云各种产物的最新流动,优惠券领取点击进入
3.广告同盟: 整理了现在主流的广告同盟平台,若是你有流量,可以作为参考选择适合你的平台点击进入
链接: http://www.fly63.com/article/detial/411