workerman listen 监控

news/2024/7/3 10:54:28
void Worker::listen(void)

用于实例化Worker后执行监听。

此方法主要用于在Worker进程启动后动态创建新的Worker实例,能够实现同一个进程监听多个端口,支持多种协议。需要注意的是用这种方法只是在当前进程增加监听,并不会动态创建新的进程,也不会触发onWorkerStart方法。

例如一个http Worker启动后实例化一个websocket Worker,那么这个进程即能通过http协议访问,又能通过websocket协议访问。由于websocket Worker和http Worker在同一个进程中,所以它们可以访问共同的内存变量,共享所有socket连接。可以做到接收http请求,然后操作websocket客户端完成向客户端推送数据类似的效果。

注意:

如果PHP版本<=7.0,则不支持在多个子进程中实例化相同端口的Worker。例如A进程创建了监听2016端口的Worker,那么B进程就不能再创建监听2016端口的Worker,否则会报Address already in use错误。例如下面的代码是无法运行的。

use Workerman\Worker;
require_once __DIR__ . '/Workerman/Autoloader.php';

$worker = new Worker();
// 4个进程
$worker->count = 4;
// 每个进程启动后在当前进程新增一个Worker监听
$worker->onWorkerStart = function($worker)
{
    /**
     * 4个进程启动的时候都创建2016端口的Worker
     * 当执行到worker->listen()时会报Address already in use错误
     * 如果worker->count=1则不会报错
     */
    $inner_worker = new Worker('http://0.0.0.0:2016');
    $inner_worker->onMessage = 'on_message';
    // 执行监听。这里会报Address already in use错误
    $inner_worker->listen();
};

$worker->onMessage = 'on_message';

function on_message($connection, $data)
{
    $connection->send("hello\n");
}

// 运行worker
Worker::runAll();

如果您的PHP版本>=7.0,可以设置Worker->reusePort=true, 这样可以做到多个子进程创建相同端口的Worker。见下面的例子:

use Workerman\Worker;
require_once './Workerman/Autoloader.php';

$worker = new Worker('text://0.0.0.0:2015');
// 4个进程
$worker->count = 4;
// 每个进程启动后在当前进程新增一个Worker监听
$worker->onWorkerStart = function($worker)
{
    $inner_worker = new Worker('http://0.0.0.0:2016');
    // 设置端口复用,可以创建监听相同端口的Worker(需要PHP>=7.0)
    $inner_worker->reusePort = true;
    $inner_worker->onMessage = 'on_message';
    // 执行监听。正常监听不会报错
    $inner_worker->listen();
};

$worker->onMessage = 'on_message';

function on_message($connection, $data)
{
    $connection->send("hello\n");
}

// 运行worker
Worker::runAll();

示例 php后端及时推送消息给客户端

原理:

1、建立一个websocket Worker,用来维持客户端长连接

2、websocket Worker内部建立一个text Worker

3、websocket Worker 与 text Worker是同一个进程,可以方便的共享客户端连接

4、某个独立的php后台系统通过text协议与text Worker通讯

5、text Worker操作websocket连接完成数据推送

代码及步骤

push.php

<?php
use Workerman\Worker;
require_once './Workerman/Autoloader.php';
// 初始化一个worker容器,监听1234端口
$worker = new Worker('websocket://0.0.0.0:1234');

/*
 * 注意这里进程数必须设置为1,否则会报端口占用错误
 * (php 7可以设置进程数大于1,前提是$inner_text_worker->reusePort=true)
 */
$worker->count = 1;
// worker进程启动后创建一个text Worker以便打开一个内部通讯端口
$worker->onWorkerStart = function($worker)
{
    // 开启一个内部端口,方便内部系统推送数据,Text协议格式 文本+换行符
    $inner_text_worker = new Worker('text://0.0.0.0:5678');
    $inner_text_worker->onMessage = function($connection, $buffer)
    {
        // $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)
{
    global $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)
{
    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();

启动后端服务
php push.php start -d

前端接收推送的js代码

var ws = new WebSocket('ws://127.0.0.1:1234');//本地电脑可以这样测试,但是一在正式服务器的,我们可以域名+端口号 就可以了,千万别用外网的ip写在页面上(安全性问题)
ws.onopen = function(){
    var uid = 'uid1';
    ws.send(uid);
};
ws.onmessage = function(e){
    alert(e.data);
};

 后端推送消息的代码

// 建立socket连接到内部推送端口
$client = stream_socket_client('tcp://127.0.0.1:5678', $errno, $errmsg, 1);
// 推送的数据,包含uid字段,表示是给这个uid推送
$data = array('uid'=>'uid1', 'percent'=>'88%');
// 发送数据,注意5678端口是Text协议的端口,Text协议需要在数据末尾加上换行符
fwrite($client, json_encode($data)."\n");
// 读取推送结果
echo fread($client, 8192);

 


http://www.niftyadmin.cn/n/2367938.html

相关文章

vim显示行号、语法高亮、自动缩进的设置

在UBUNTU中vim的配置文件存放在/etc/vim目录中&#xff0c;配置文件名为vimrc在Fedora中vim的配置文件存放在/etc目录中&#xff0c;配置文件名为vimrc在终端 输入以下命令来编辑vimrc配置文件&#xff1a; sudo vim /etc/vim/vimrc 或者 sudo gedit /etc/vim/vimrc1、显示行号…

Delphi----怎样保证程序只运行一个实例

在project启动文件编辑以下内容&#xff0c;可保证程序只运行一个实例。 var mymutex: THandle;beginmymutex : CreateMutex(nil, True, 营收数据自检系统);if GetLastError <> ERROR_ALREADY_EXISTS thenbeginApplication.Initialize;Application.Title : 营收数据自检系…

改变linux终端颜色 和 终端提示符

如果您很容易使 shell 提示行变得色彩绚烂斓且带有更多信息&#xff0c;为什么还要坚持用单调的标准 shell 提示行呢&#xff1f;在这篇技巧中&#xff0c;Daniel Robbins 将说明如何获得符合您的意愿的 shell 提示行&#xff0c;并会说明如何动态更新 X 终端的标题栏。 作为 L…

Delph-- 关闭程序后托盘图标显示

1.需要引入UnitTrayIcon.pas文件(见附件)2.声明双击事件procedure trayDblClick(Sender: TObject); 3.功能实现 var frmMain: TfrmMain; tray: TTrayNotifyIcon; //窗口初始化 procedure TfrmMain.FormCreate(Sender: TObject); begin tray : TTrayNotifyIcon.Create(s…

mysql 性能优化,减轻数据库的压力。(减少数据库查询的次数)

查询订单相应的user_id的详细 $arr array(1>array(user_id > 5,good_id > 361),2>array(user_id > 63,good_id > 3663),3>array(user_id > 75,good_id > 3663), ); 我们习惯性&#xff1a;使用 foreach 遍历数据&#xff0c;select 查询一条数据…

vim插件ctags用法介绍 及编译安装

ctags是vim的一个非常有用的插件&#xff0c;可以大大提高程序编码(C、C)的效率&#xff0c;比如快速掉转到函数、变量等的定义处【目的】在RHEL 5上面安装配置vim插件ctags【前提条件】vim已经安装【安装ctags】1、首先确定自己是否已经安装了ctags&#xff1a;[code"jav…

Delphi-- 如何设置程序开机运行(写注册表)

1.需引入注册表单元Registry //------------------------------------------------------------------------------ // 开机运行选项 //------------------------------------------------------------------------------ procedure TfrmMain.ckAutoRunClick(Sender: TObject…

mysql索引的常识

1、索引类型 Mysql目前主要有以下几种索引类型&#xff1a;FULLTEXT&#xff0c;HASH&#xff0c;BTREE&#xff0c;RTREE。 1. FULLTEXT 即为全文索引&#xff0c;目前只有MyISAM引擎支持。其可以在CREATE TABLE &#xff0c;ALTER TABLE &#xff0c;CREATE INDEX 使用&…