网站首页  词典首页

请输入您要查询的论文:

 

标题 PHP使用WebSwoole来实现消息推送
范文

    邓绪高

    摘要:在一个博客系统中,经常会使用到消息推送系统来发送一些通知给登录用户。如博主需要发送某个消息给所有登录用户,或者某个用户对另一个用户的评论进行了回复等等。该文利用WebSwoole技术来实现点对点的消息推送提醒。

    关键词:PHP;WebSwoole;消息推送

    中图分类号:TP311 文献标识码:A 文章编号:1009-3044(2018)25-0091-02

    1 前言

    B/S结构的软件项目中有时客户端需要实时的获得服务器消息,但默认HTTP协议只支持请求响应模式。这样做可以简化Web服务器,减少服务器的负担,加快响应速度,因为服务器不需要与客户端长时间建立一个通信链接,但不容易直接完成实时的消息推送功能,如聊天室、后台消息提醒、实时更新数据等功能,但通过polling、Long polling、长连接、Flash Socket以及HTML5中定义的WebSocket能完成该功能需要。

    1.1 Socket简介

    Socket又称“套接字”,应用程序通常通过"套接字"向网络发出请求或者应答网络请求。Socket的英文原义是“孔”或“插座”,作为UNIX的进程通信机制。Socket可以实现应用程序间网络通信。

    1.2 WebSocket简介与消息推送

    B/S架构的系统多使用HTTP协议,HTTP协议的特点:

    1)无状态协议;

    2) 用于通过 Internet 发送请求消息和响应消息;

    3) 使用端口接收和发送消息,默认为80端口。

    底层通信还是使用Socket完成。HTTP协议决定了服务器与客户端之间的连接方式,无法直接实现消息推送。

    WebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。依靠这种技术可以实现客户端和服务器端的长连接,双向实时通信。特点:1)事件驱动;2)异步;3)使用ws或者wss协议的客户端socket。

    能够实现真正意义上的推送功能。

    1.3 WebSocket客户端

    websocket允许通过JavaScript建立与远程服务器的连接,从而实现客户端与服务器间双向的通信。在websocket中有两个方法:

    1)send() 向远程服务器发送数据;2)close() 关闭该websocket链接。

    websocket同时还定义了几个监听函数:

    1)onopen 当网络连接建立时触发该事件;2)onerror 当网络发生错误时触发该事件;3)onclose 当websocket被关闭时触发该事件;4)onmessage 当websocket接收到服务器发来的消息的时触发的事件,也是通信中最重要的一个监听事件。

    websocket的url开头是ws,如果需要ssl加密可以使用wss,当我们调用websocket的构造方法构建一个websocket对象(new WebSocket(url))的之后,就可以进行即时通信了。

    2 需求分析

    以博客系统中评论被回复为例,当一条评论被其他某个用户(假设是用户B)回复,即发一条通知给被回复的评论所属人(假设是用户A),告诉A,他的评论被回复了。

    2.1 功能分析:

    1)我们不能保证用户B和用户A都处于连接状态,但是通常情况下,用户B至少是连接状态,用户A不一定跟server保持连接;

    2)任一用户都不止对应一个客户端。换言之,用户A和用户B都可能打开了多个tab页,对于一个tab页,就会有一个独立的fd标识,我们这里认为任一用户只有最新的fd有效,或者你可以认为用户所有的tab页的连接都有效;

    3)因为没有用户系统,我们以get传递的参数uid为标识,uid=100视为用户A,uid=101视为用户B;

    4)我们不准备做一个评论系统,我们模拟的tab页包将会包含一个输入内容的文本框、一个输入目标uid的input和一个发送的按钮以满足需求。

    2.2流程分析:

    1)户A($_GET['uid'] = 100)在某个tab页的输入框输入“回复xxx的内容”字样后,点击发送。

    2)户B($_GET['uid'] = 101)如果处于连接状态,则alert提醒用户B,他的评论被回复了。

    3关键代码实现

    将WebSwoole的创建和相关的回调封装到一个类中,服务器端代码逻辑如下:

    1)我们给CommentServer类增加了一个属性 $user2fd,这个是key => value结构,用于保存uid和fd的映射关系。

    2)onOpen回调做两件事,验证授权和添加新的映射关系。

    3)onMessage回调只接收含有event项的数组,event等同于CommentServer类的方法名,我们这里只有一个用于web通知的alertTip方法。

    此外,我们封装了该类的close方法和push方法,close方法用于server主动关闭连接,删除uid和fd的映射,push方法用于向指定的fd推送消息

    class CommentServer

    { private $_serv; //webswoole变量

    public $key = '^abc&swoole;$';//token的生成鑰匙

    // 用户id和fd对应的映射,key => value,key是用户的uid,value是用户的fd

    public $user2fd = [];

    public function __construct()

    { $this->_serv = new swoole_websocket_server("127.0.0.1", 9501); //创建webswoole

    $this->_serv->set([

    'worker_num' => 1,

    'heartbeat_check_interval' => 60,//心跳检测

    'heartbeat_idle_time' => 125,

    ]);

    //绑定回调

    $this->_serv->on('open', [$this, 'onOpen']);

    $this->_serv->on('message', [$this, 'onMessage']);

    $this->_serv->on('close', [$this, 'onClose']);

    }

    public function onOpen($serv, $request)

    { // 连接授权

    $accessResult = $this->checkAccess($serv, $request);

    if (!$accessResult) {

    return false;

    }

    if (array_key_exists($request->get['uid'], $this->user2fd)) {

    始终把用户最新的fd跟uid映射在一起

    return false;

    } else {

    $this->user2fd[$request->get['uid']] = $request->fd;}}

    public function onMessage($serv, $frame)

    {// 校验数据的有效性,数据被`json_decode`处理之后是数组并且数组的`event`项非空才是有效数据

    // 非有效数据,关闭该连接

    $data = $frame->data;

    $data = json_decode($data, true);

    if (非有效数据) {关闭该连接}

    // 根据数据的`event`项,判断要做什么,`event`映射到当前类具体的某一个方法,方法不存在则关闭连接

    $method = $data['event'];

    if (方法不存在) {关闭连接}

    $this->$method($frame->fd, $data); }//执行当前类的某个具体方法

    //webswoole服务器端在收到客户端数据后要执行的操作

    public function alertTip($fd, $data)

    { if (推送目标用户的uid非真或者该uid尚无保存的映射fd) {

    关闭连接

    }

    //向目标用户推送消息提醒

    $this->push(目标用户, ['event' => $data['event'], 'msg' => '收到一条新的回复.']);

    }

    public function start()

    {

    $this->_serv->start();

    }}

    客户端代码如下CommentClient.php:

    

    发送内容:

    发送给谁:

    

    

    

    

    在浏览器中访问127.0.0.1/commentclient.php?uid=101时,会有两个输入框,一个填写消息推送内容,一个填写目标用户,点击发送,则在线的目标用户能马上收到消息提醒。

    4 总结

    该消息推送功能是在没有用户系统的情况下实现的,所以只能硬编码了两个用户A和B进行模拟,并且当目标用户B不在线时,他是收不到消息提醒的,如果想在目标用户上线后依然能收到消息提醒,可以先把对A的评论通知存储起来,在用户A连接的时候在进行通知。

    参考文献:

    [1] Matt Zandstra.深入PHP:面向对象、模式与实践[M].北京:人民邮電出版社,2011.

    [2] Yii Framework中文网文档中心[EB/OL].https://www.yiichina.com/doc.

    [3] 白狼栈[EB/OL]. http://www.manks.top/.

    【通联编辑:张薇】

随便看

 

科学优质学术资源、百科知识分享平台,免费提供知识科普、生活经验分享、中外学术论文、各类范文、学术文献、教学资料、学术期刊、会议、报纸、杂志、工具书等各类资源检索、在线阅读和软件app下载服务。

 

Copyright © 2004-2023 puapp.net All Rights Reserved
更新时间:2025/3/12 11:36:54