侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

基于workerman的实时推送(摒弃ajax轮询)

技术  /  管理员 发布于 8年前   211

下面由workerman教程栏目给大家介绍实现基于workerman的实时推送,摒弃ajax轮询的方法,希望对需要的朋友有所帮助!

先扯些这些内容:

TCP/IP

TCP/IP是个协议组,可分为三个层次:网络层、传输层和应用层。

在网络层有IP协议、ICMP协议、ARP协议、RARP协议和BOOTP协议。

在传输层中有TCP协议与UDP协议。

在应用层有:

TCP包括FTP、HTTP、TELNET、SMTP等协议

UDP包括DNS、TFTP等协议

短连接

连接->传输数据->关闭连接

HTTP是无状态的,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接。

也可以这样说:短连接是指SOCKET连接后发送后接收完数据后马上断开连接。

长连接

连接->传输数据->保持连接 -> 传输数据-> 。。。 ->关闭连接。

长连接指建立SOCKET连接后不管是否使用都保持连接,但安全性较差。

http的长连接

HTTP也可以建立长连接的,使用Connection:keep-alive,HTTP 1.1默认进行持久连接。HTTP1.1和HTTP1.0相比较而言,最大的区别就是增加了持久连接支持(貌似最新的 http1.0 可以显示的指定 keep-alive),但还是无状态的,或者说是不可以信任的。

什么时候用长连接,短连接?

长连接多用于操作频繁,点对点的通讯,而且连接数不能太多情况,。每个TCP连接都需要三步握手,这需要时间,如果每个操作都是先连接,再操作的话那么处理速度会降低很多,所以每个操作完后都不断开,次处理时直接发送数据包就OK了,不用建立TCP连接。例如:数据库的连接用长连接, 如果用短连接频繁的通信会造成socket错误,而且频繁的socket 创建也是对资源的浪费。

而像WEB网站的http服务一般都用短链接,因为长连接对于服务端来说会耗费一定的资源,而像WEB网站这么频繁的成千上万甚至上亿客户端的连接用短连接会更省一些资源,如果用长连接,而且同时有成千上万的用户,如果每个用户都占用一个连接的话,那可想而知吧。所以并发量大,但每个用户无需频繁操作情况下需用短连好。

workerman是啥子?Workerman是一款纯PHP开发的开源高性能的PHP socket 服务器框架。被广泛的用于手机app、移动通讯,微信小程序,手游服务端、网络游戏、PHP聊天室、硬件通讯、智能家居、车联网、物联网等领域的开发。 支持TCP长连接,支持Websocket、HTTP等协议,支持自定义协议。拥有异步Mysql、异步Redis、异步Http、异步消息队列等众多高性能组件。

开始步入正题:为了达到实时通讯,很多时候我们采用了ajax轮询机制,如图:

8a6a3f3a91373e2376d3e9557dc4fa8.png

后面可以采用workerman方式来实现,项目也是tp写的,官方手册这么说到

与其它mvc框架结合建议以上图的方式(ThinkPHP为例):

1、ThinkPHP与Workerman是两个独立的系统,独立部署(可部署在不同服务器),互不干扰。

2、ThinkPHP以HTTP协议提供网页页面在浏览器渲染展示。

3、ThinkPHP提供的页面的js发起websocket连接,连接workerman

4、连接后给Workerman发送一个数据包(包含用户名密码或者某种token串)用于验证websocket连接属于哪个用户。

5、仅在ThinkPHP需要向浏览器推送数据时,才调用workerman的socket接口推送数据。

6、其余请求还是按照原本ThinkPHP的HTTP方式调用处理。

总结:

把Workerman作为一个可以向浏览器推送的通道,仅仅在需要向浏览器推送数据时才调用Workerman接口完成推送。业务逻辑全部在ThinkPHP中完成。

ok,到这里,把workerman容器跑起来,注意这里是CLI模式运行

619de260e068fef7e4de9ac451916d9.png

然后再我们项目接收信息中这么玩,附上代码

<script>    // 连接服务端    var socket = io('http://127.0.0.1:2120');    // uid可以是自己网站的用户id,以便针对uid推送    uid = 123;    // socket连接后以uid登录    socket.on('connect', function(){    socket.emit('login', uid);    });    // 后端推送来消息时    socket.on('new_msg', function(msg){        console.log("收到消息:"+msg);  //自己业务逻辑处理    });    </script>

接着,我们在用户向用户发送信息的时候添加

// 指明给谁推送,为空表示向所有在线用户推送        $to_uid = "123";        // 推送的url地址        $push_api_url = "http://127.0.0.1:2121/";        $post_data = array(           "type" => "publish",           "content" => "数据",           "to" => $to_uid,         );        $ch = curl_init ();        curl_setopt ( $ch, CURLOPT_URL, $push_api_url );        curl_setopt ( $ch, CURLOPT_POST, 1 );        curl_setopt ( $ch, CURLOPT_HEADER, 0 );        curl_setopt ( $ch, CURLOPT_RETURNTRANSFER, 1 );        curl_setopt ( $ch, CURLOPT_POSTFIELDS, $post_data );        curl_setopt ($ch, CURLOPT_HTTPHEADER, array("Expect:"));        $return = curl_exec ( $ch );        curl_close ( $ch );        var_export($return);

其中,workerman里面的推送核心代码实现

// 全局数组保存uid在线数据$uidConnectionMap = array();// 记录最后一次广播的在线用户数$last_online_count = 0;  // PHPSocketIO服务$sender_io = new SocketIO(2120);// 客户端发起连接事件时,设置连接socket的各种事件回调 // 当$sender_io启动后监听一个http端口,通过这个端口可以给任意uid或者所有uid推送数据$sender_io->on('workerStart', function(){    // 监听一个http端口    $inner_http_worker = new Worker('http://0.0.0.0:2121');    // 当http客户端发来数据时触发    $inner_http_worker->onMessage = function($http_connection, $data){        global $uidConnectionMap;        $_POST = $_POST ? $_POST : $_GET;        // 推送数据的url格式 type=publish&to=uid&content=xxxx        switch(@$_POST['type']){            case 'publish':                global $sender_io;                $to = @$_POST['to'];                $_POST['content'] = htmlspecialchars(@$_POST['content']);                // 有指定uid则向uid所在socket组发送数据                if($to){                    $sender_io->to($to)->emit('new_msg', $_POST['content']);                // 否则向所有uid推送数据                }else{                    $sender_io->emit('new_msg', @$_POST['content']);                }                // http接口返回,如果用户离线socket返回fail                if($to && !isset($uidConnectionMap[$to])){                    return $http_connection->send('offline');                }else{                    return $http_connection->send('ok');                }        }        return $http_connection->send('fail');    };    }); if(!defined('GLOBAL_START')){    Worker::runAll();}

ok,大功告成!

以上就是基于workerman的实时推送(摒弃ajax轮询)的详细内容,更多请关注其它相关文章!


  • 上一条:
    ajax获取网页添加到div中的方法
    下一条:
    原生JS封装AJAX方法
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 2024.07.09日OpenAI将终止对中国等国家和地区API服务(0个评论)
    • 2024/6/9最新免费公益节点SSR/V2ray/Shadowrocket/Clash节点分享|科学上网|免费梯子(1个评论)
    • 近期文章
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2017-07
    • 2017-08
    • 2017-09
    • 2018-01
    • 2018-07
    • 2018-08
    • 2018-09
    • 2018-12
    • 2019-01
    • 2019-02
    • 2019-03
    • 2019-04
    • 2019-05
    • 2019-06
    • 2019-07
    • 2019-08
    • 2019-09
    • 2019-10
    • 2019-11
    • 2019-12
    • 2020-01
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2020-10
    • 2020-11
    • 2021-04
    • 2021-05
    • 2021-06
    • 2021-07
    • 2021-08
    • 2021-09
    • 2021-10
    • 2021-12
    • 2022-01
    • 2022-02
    • 2022-03
    • 2022-04
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-02
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-06
    • 2023-07
    • 2023-08
    • 2023-09
    • 2023-10
    • 2023-12
    • 2024-02
    • 2024-04
    • 2024-05
    • 2024-06
    • 2025-02
    • 2025-07
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客