如何在php后端及时推送消息给客户端

walkor大神,目前需求是这样的:

有一群商家在后台网页处理批量导入产品 -》 服务器接受请求 -》 开始foreach一个一个处理导入请求;

我现在想每成功导入一个就推送到前台显示已经导入成功,直到全部导入自动结束推送。

看了聊天室代码,消息推送都是靠前端js+event.php,我想直接在php里面不需要onMessage触发.

我从下午看到现在文档,也看了很多问答,依然非常糊涂,不奢望给整段代码,但是希望walkor大神给点思路。
2015-08-21 添加评论
分享

36 个回复

 

walkor

赞同来自: vsgeping osacar ivan hnxymjj gzchen 更多 »

后端代码
push.php
<?php
	use Workerman\Worker;
	require_once './Workerman/Autoloader.php';
	// 初始化一个worker容器,监听1234端口
	global $worker;
	$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();


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

前端接收推送的js代码
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);
    };


后端推送消息的代码
// 建立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);


这里的uid不一定是用户的id,也可以理解为任务id即 taskid

以上代码亲测可以直接使用

转载于:https://my.oschina.net/u/3371661/blog/3013385

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值