视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
workerman中后端消息实时推送至前端的方法
2020-11-03 18:20:05 责编:小采
文档

在开发过程中,我们经常会遇到如下这种情况。前端列表展示后台数据库中的数据,但是在后台的某一个接口中向数据库插入一条数据,此时数据库已更新,但是前端展示数据并没有更新,需要手动刷新才可以。但是每次都自己手动更新,太麻烦了,这时候就可以用到workerman来解决问题了。

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

那我们应该如何能使用才能解决上述问题呢?

1.前后端建立websocket的长连接,用于互相的消息推送

2.后端内部在建立一个监听进程(协议不限)

3.在接口往数据库中插入数据成功后,想内部监听端口推送数据

4.在收到内部监听端口的推送消息之后,后端在向前端通过websocket推送消息,实现刷新

在下载好workerman框架源码后,我们来实现上述过程。

实现代码:

server.php

<?php
use WorkermanWorker;
 
require_once __DIR__ . '/../../vendor/autoload.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();

push.php

<?php
//插入数据库操作
 
// 建立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)."
");
// 读取推送结果
echo fread($client, 8192);
 
 ?>

clien.html

<!DOCTYPE html>
<html>
<head>
	<title></title>
</head>
<body>
<script>
	var ws = new WebSocket('ws://127.0.0.1:1234');
	ws.onopen = function(){
	var uid = 'uid1';
	ws.send(uid);
	};
	ws.onmessage = function(e){
	//alert(e.data);
	console.log(e.data);
	//window.location.reload();
	};
</script>
</body>
</html>

运行流程:

打开cmd,运行server.php

打开前端页面和console

在打开一个cmd,运行push.php

此时在看前端页面,console就收收到消息。

更多workerman知识请关注PHP中文网workerman框架教程栏目。

下载本文
显示全文
专题