伍佰目录 短网址
  当前位置:海洋目录网 » 站长资讯 » 站长资讯 » 文章详细 订阅RssFeed

PHP实时消息推送,你会不会用workerman

来源:本站原创 浏览:111次 时间:2022-06-05

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轮询机制,后面可以采用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模式运行

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

<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();
}


为了你能更好的学习workerman,小编在这里推荐一套视频教程:【TP5与workerman实战在线客服视频教程】,以下是课程简介,课程目录与下载地址:http://www.mano100.cn/thread-158-1-1.html

【课程概述】

为了带领大家深入学习workerman以及getwayworker,让大家迅速在自己项目中使用workerman,本次课程以在线客服为例进行详细系统的实战教程讲解,使用Websocket协议,实现长连接,摆脱长轮询,详细完整的讲解如何利用workerman开发即时通讯,并且部署到自己的项目里以及运行在Linux系统里面。不管你的项目是基于ThinkPHP还是laravel或者yii,甚至微擎,不管你是pc端应用还是移动端应用,本次教程都教会如何在自己的项目里面完整的实现在线客服这个模块。你也可以之前对Websocket协议毫无了解,本次教程重在实战。

【课程目录】章节1牛刀小试workerman
课时1workerman介绍及项目环境搭建10:55
课时2workerman整合入项目及长连接实现群发功能初次体验16:26
课时3workerman群发及客户端和socket服务器保持长连接双向消息推送31:03
课时4长连接绑定用户id实现实现一对一客服聊天28:35

章节2在线客服项目实战(workerman+tp5)
课时5getwayworker长连接下的普通文本消息之聊天记录持久化37:22
课时6长连接下聊天页面展示项目中用户头像和对方昵称20:47
课时7长连接下聊天页面之聊天记录初始化21:09
课时8长连接下聊天页面之展示对方在线状态16:17
课时9长连接下聊天页面之发送图片消息(1)27:53
课时10长连接下聊天页面之发送图片消息(2)28:46
课时11长连接下聊天页面之QQ表情发送15:01

章节3整合入项目
课时12聊天列表初始化之数据获取28:31
课时13长连接下实现聊天列表实时更新24:40
课时14极其重要!!所有页面加入长连接大总结,灵活运用在自己项目.29:27

章节4项目上线
课时15getwayworker 即时通讯部署到Linux系统


【下载地址】

链接:http://www.mano100.cn/thread-158-1-1.html


  推荐站点

  • At-lib分类目录At-lib分类目录

    At-lib网站分类目录汇集全国所有高质量网站,是中国权威的中文网站分类目录,给站长提供免费网址目录提交收录和推荐最新最全的优秀网站大全是名站导航之家

    www.at-lib.cn
  • 中国链接目录中国链接目录

    中国链接目录简称链接目录,是收录优秀网站和淘宝网店的网站分类目录,为您提供优质的网址导航服务,也是网店进行收录推广,站长免费推广网站、加快百度收录、增加友情链接和网站外链的平台。

    www.cnlink.org
  • 35目录网35目录网

    35目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向35目录推荐、提交优秀网站。

    www.35mulu.com
  • 就要爱网站目录就要爱网站目录

    就要爱网站目录,按主题和类别列出网站。所有提交的网站都经过人工审查,确保质量和无垃圾邮件的结果。

    www.912219.com
  • 伍佰目录伍佰目录

    伍佰网站目录免费收录各类优秀网站,全力打造互动式网站目录,提供网站分类目录检索,关键字搜索功能。欢迎您向伍佰目录推荐、提交优秀网站。

    www.wbwb.net