zoukankan      html  css  js  c++  java
  • windows上Yii2使用workerman整套流程

    1.在根目录下新建Worker目录 进入新建的Worker文件夹 运行 LINUX下运行 composer require workerman/workerman win 下运行 composer require workerman/workerman-for-win

    2.Worker文件夹 下新建文件push.php

    <?php
    //require_once __DIR__ .'/vendor/autoload.php';
    require_once __DIR__ .'/vendor/workerman/workerman/Autoloader.php';  
    //  require_once __DIR__ .'/vendor/workerman/workerman-for-win/Autoloader.php';  WIN下的引用
    use WorkermanWorker;
    //
    // 初始化一个worker容器,监听1234端口
    $worker = new Worker('websocket://0.0.0.0:1234');
    // 这里进程数必须设置为1
    $worker->count = 1;
    // worker进程启动后建立一个内部通讯端口
    $worker->onWorkerStart = function($worker)
    {
        // 开启一个内部端口,方便内部系统推送数据,Text协议格式 文本+换行符
        $inner_text_worker = new Worker('Text://0.0.0.0:5678');
        $inner_text_worker->onMessage = function($connection, $buffer)
        {
            global $worker;
            // $data数组格式,里面有uid,表示向那个uid的页面推送数据
            $data = json_decode($buffer, true);
            $uid = $data['uid'];
            // 通过workerman,向uid的页面推送数据
            $ret = sendMessageByUid($uid, $buffer);
            // 返回推送结果
            $connection->send($ret ? 'ok' : 'fail');
        };
        $inner_text_worker->listen();
    };
    // 新增加一个属性,用来保存uid到connection的映射
    $worker->uidConnections = array();
    // 当有客户端发来消息时执行的回调函数
    $worker->onMessage = function($connection, $data)use($worker)
    {
    
        // 判断当前客户端是否已经验证,既是否设置了uid
        if(!isset($connection->uid))
        {
            // 没验证的话把第一个包当做uid(这里为了方便演示,没做真正的验证)
            $connection->uid = $data;
            /* 保存uid到connection的映射,这样可以方便的通过uid查找connection,
             * 实现针对特定uid推送数据
             */
            $worker->uidConnections[$connection->uid] = $connection;
            return;
        }
    };
    
    // 当有客户端连接断开时
    $worker->onClose = function($connection)use($worker)
    {
        global $worker;
        if(isset($connection->uid))
        {
            // 连接断开时删除映射
            unset($worker->uidConnections[$connection->uid]);
        }
    };
    
    // 向所有验证的用户推送数据
    function broadcast($message)
    {
        global $worker;
        foreach($worker->uidConnections as $connection)
        {
            $connection->send($message);
        }
    }
    
    // 针对uid推送数据
    function sendMessageByUid($uid, $message)
    {
        global $worker;
        if(isset($worker->uidConnections[$uid]))
        {
            $connection = $worker->uidConnections[$uid];
            $connection->send($message);
            return true;
        }
        return false;
    }
    
    // 运行所有的worker(其实当前只定义了一个)
    Worker::runAll();


    3.controllers 下添加PushController.php

    <?php
    namespace backendcontrollers;
    
    use Yii;
    use yiiwebController;
    
    class PushController extends Controller
    {
        /**
         * Renders the index view for the module
         * @return string
         */
       public function actionWorker()
        {
            // 建立socket连接到内部推送端口
            $client = stream_socket_client('tcp://127.0.0.1:5678', $errno, $errmsg, 1);
    // 推送的数据,包含uid字段,表示是给这个uid推送
            echo 'ERRER:'.$errno.'='.$errmsg;
            $data = array('uid'=>'uid1', 'percent'=>'88%测试');
    // 发送数据,注意5678端口是Text协议的端口,Text协议需要在数据末尾加上换行符
            fwrite($client, json_encode($data)."
    ");
    // 读取推送结果
            echo '$client=='.$client;
            echo fread($client, 8192);
    
            //return $this->render('index');
        }
    }
    4.前端测试test.html
    <!DOCTYPE html>
    <html>
    
    <head lang="en">
        <meta charset="utf-8">
        <title></title>
    </head>
    
    <body>
        <h3>WebSocket协议的客户端程序</h3>
        <button id="btConnect">连接到WS服务器</button>
        <button id="btSendAndReceive">向WS服务器发消息并接收消息</button>
        <button id="btClose">断开与WS服务器的连接</button>
        <div id="val"></div>
    <script type="text/javascript">
        var wsClient=null;
        btConnect.onclick=function(){
            wsClient=new WebSocket('ws://127.0.0.1:1234'); //这个端口号和容器监听的端口号一致
            console.log(wsClient)
            wsClient.onopen = function(){
                var uid = 'uid1';
                // 表名自己是uid1
                wsClient.send(uid);
                console.log('ws客户端已经成功连接到服务器上')
            }
            wsClient.onmessage = function(e){
                console.log('ws客户端收到一个服务器消息:'+e.data);
                val.innerHTML=e.data;
            }
        }
        btSendAndReceive.onclick = function(){
            wsClient.send('Hello Server');
            wsClient.onmessage = function(e){
                console.log('ws客户端收到一个服务器消息:'+e.data);
                val.innerHTML=e.data;
            }
        }
        btClose.onclick = function(){
            wsClient.close();
            wsClient.onclose = function(){
                console.log('到服务器的连接已经断开');
            }
        }
    </script>
    </body>
    </html>



    4. 模拟过程

      在终端里执行php push.php start -d, 开启服务, 等待客户端(浏览器和php客户端)连接

    .浏览器里打开test.html, 打开控制台console, 点击按钮->链接到websocket


     
    客户端接收到php推送的消息

    另开一个终端, 执行php PushController中的actionWorker方法或者浏览器访问该地址, 此时再客户端就能看到php推送过来的消息, 从而完成一次交互

     
    .随后接收到服务器返回消息
  • 相关阅读:
    如何基于日志,同步实现数据的一致性和实时抽取?
    实例解说AngularJS在自动化测试中的应用
    漏洞管理平台『洞察』部署指南
    UAVStack的慢SQL数据库监控功能及其实现
    淡说Linux 的发展史
    一张图告诉你E-R图怎么画
    一张图告诉你UML图怎么画❀
    最简单,最明了,看了就会的VScode和C++的配置!(Visual Studio Code)
    用Eclipse开发项目,你不能不知道的快捷键
    什么年代了,你还不会用油猴刷网课!
  • 原文地址:https://www.cnblogs.com/wangrongjie/p/12427609.html
Copyright © 2011-2022 走看看