如何在php後端及時推送消息給客戶端

walkor大神,目前需求是這樣的:

有一羣商家在後臺網頁處理批量導入產品 -》 服務器接受請求 -》 開始foreach一個一個處理導入請求;

我如今想每成功導入一個就推送到前臺顯示已經導入成功,直到所有導入自動結束推送。

看了聊天室代碼,消息推送都是靠前端js+event.php,我想直接在php裏面不須要onMessage觸發.

我從下午看到如今文檔,也看了不少問答,依然很是糊塗,不奢望給整段代碼,可是但願walkor大神給點思路。
2015-08-21 添加評論
分享

36 個回覆

 

walkorphp

贊同來自: 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 以上代碼親測能夠直接使用
相關文章
相關標籤/搜索