/ BS推送  workerman  html5推送框架  php推送框架 

基于Wokerman快速构建服务端到前端的推送框架


        推送,是现在软件开发的一个很基础的功能,用于后端向前端主动传递消息,我们可能用的比较常见的就是APP的推送,这里不详解。我们现在要说的是服务器对浏览器的推送,通常比较常见的有AJAX,Comet,ServerSent以及WebSocket。


AJAX

正常的一个页面在浏览器中是这样工作的:

用户向给予浏览器一个需要访问的地址

浏览器根据这个地址访问服务器,并与服务器之间创建一个TCP连接(HTTP请求)

服务器根据这个地址和一些其它数据,组建一段HTML文本,将写入TCP连接,然后关闭连接

浏览器得到了来自服务器的HTML文本,解析并呈现了浏览器上给用户浏览

此时,用户点击了网站上任何一个<a>或触发任何一个<form>提交时:


浏览器根据form的参数或者a的参数,作为访问的地址

与服务器创建TCP连接

服务器组建HTML文本,然后关闭连接

浏览器将当前显示的页面摧毁,并按照新的HTML文本呈现一个新的页面给用户

我们不难发现的是整个过程中间,一旦建立了一个连接,页面就无法再维护住了。整个过程看上去有点强买强卖,也许我只要一杯新的可乐,但你非要给我一整个套餐组合。


此时我们可以了解一下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轮循成为了一种很普遍的手段。

Comet

我们知道HTTP请求其实是基于TCP连接实现的,再看看之前说的HTTP请求处理过程:


客户端与服务器建立TCP连接

服务器根据客户端提交的报文处理并生成HTML文本

将HTML封闭成为HTTP协议报文并返回给客户端

关闭链接。

看到这个处理过程,我们不难联想到,如果把第4步——关闭连接给省掉,那不就相当于有一个长连接一直被维持住了么。通过对服务端的一些操作,我们可以直接将数据从这个TCP连接发送客户端了。


通过这种技术,我们可以大大提高服务器推送的实时性,还可以减去服务端不停地建立、施放连接所形成的开销。


目前市面上有不少基于AJAX实现的Comet机制,但主要有两种方式:


建立连接后依然使用"询问"+"应答"的模式。虽然工作方式没变,但是因为减去了每次建立与施放连接的工作,所以性能上提升了很多。而且服务器对TCP连接可以有上下文的定义,而不像以前的AJAX完全是无状态的。

通过对Stream的写入实现服务器将数据主动发送到客户端。因为是TCP连接,所以通过对服务器的编程,我们可以主动的把数据从服务端发送给客户端,从模式上真正建立起了推送的概念。




Server-Sent

Server-Sent是HTML5提出一个标准,它延用了Comet的思路,并对其进行了一些规范。使得Comet这项技术由原来的分支衍生技术转成了正统的官方标准。


它的原理与Comet相同,由客户端发起与服务器之间创建TCP连接,然后并维持这个连接,至到客户端或服务器中的做任何一放断开,ServerSent使用的是"问"+"答"的机制,连接创建后浏览器会周期性地发送消息至服务器询问,是否有自己的消息。

//定义一个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,具有更好的统一性,而且简单好用。


WebSocket

看名字就知道了,这是一个可以用在浏览器上的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具有较为复杂的协议,需要在服务端做额外编程才能进行数据通讯。




WebSocket + MessageQueue


MessageQueue,简称MQ,也就是消息列队。是一种常常用于Tcp服务端的技术。通过生产和访问各种消息类型,MQ服务器会将生产者所生成的消息发给感兴趣的客户端。市面上有很多的MQ框架,比如:ActiveMQ。


ActiveMQ已经支持了WebSocket协议,也就意味着,WebSocket已经可以作为一个生产者或一个消费者,与MQ服务器连接。


开发者可以通过MQTT的JS脚本,连接上MQ服务器,同时将Web服务器也连上MQ服务器,从此可以告别了Http通讯协议,完完全全使用Socket通讯来完成数据的交换。


以上就是服务端向前端推送的几个基本常用的方式,但是呢?这个对前端的实现和后台的把控都需要一定的时间和精力来调整优化,今天我带来的一个推送框架呢是一个基于纯PHP开发的开源高性能的PHP socket 服务器框架。被广泛的用于手机app、移动通讯,微信小程序,手游服务端、网络游戏、PHP聊天室、硬件通讯、智能家居、车联网、物联网等领域的开发。 支持TCP长连接,支持Websocket、HTTP等协议,支持自定义协议。拥有异步Mysql、异步Redis、异步Http、异步消息队列等众多高性能组件----Workerman,前后端人员可以基于这个快速的搭建高性能的BS推送框架,具体请在官网了解相关信息。


这里呢本博客提供已经搭建好的接口可以直接使用(因为Wokerman需要服务器的支持,而虚拟主机是不支持的):

前端登录地址:https://api.haloxin.me

后台推送地址:http://api.haloxin.me/send?type=publish&content=内容&to=目标用户

可以直接使用!本站的二维码登录就是基于本接口实现



发布评论

热门评论区: