Page

[网络编程]基于workerman的服务器推送web端简单实例

756Anson17-10-29



环境:

Workerman version: 3.5.1          

PHP version:    5.6.30

Centos version:   6.8


workerman目录结构:

 workerman

    ---App                               app开发目录

         ---ServerPush                      服务器推模块

             index.php                      

             push_tcp.php

    -+-Workerman                           wm核心目录(不修改)

    _home_workerman_App_ServerPush_index_php.pid      守护进程号id

    workerman.log                          日志文件




index.php文件:

<?php

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

$worker = new Worker('websocket://0.0.0.0:8888');
$worker->count = 1;//进程数
$worker->onWorkerStart = function()
{
   //建立text协议进程,方便服务器内部调用推送
   $inner_text_worker = new Worker('text://0.0.0.0:9988');
   $inner_text_worker->onMessage = function($connection, $buffer)
   {
      $data = json_decode($buffer, true);

      if ($data['type'] === 'broadcast') {
         //广播
         $result = broadcast($data['data']);

      } elseif ($data['type'] === 'byUid') {
         //独播
         $result = sendMessageByUid($data['uid'], $data['data']);
      }

      $connection->send($result);
   };
   $inner_text_worker->listen();
};

$worker->uidConnections = [];
$worker->onMessage = function($connection, $data)
{
   global $worker;
   //注册用户uid
   if(!isset($connection->uid))
   {
      //以用户第一次发过来的uid为编号,正常流程是用户发账号密码,通过验证后存用户id
      $connection->uid = $data;
      $worker->uidConnections[$connection->uid] = $connection;
      return;
   }
};

$worker->onClose = function($connection)
{
   global $worker;
   //用户退出时告诉服务端,并清除uid
   if(isset($connection->uid))
   {
      echo $connection->uid."已退出\n";
      unset($worker->uidConnections[$connection->uid]);
   }
};

//广播函数
function broadcast($message)
{
   global $worker;
   $sum = 0;
   foreach($worker->uidConnections as $connection)
   {
      if($connection->send($message)) $sum++;
   }
   return "['all'=>".count($worker->uidConnections).",'success'=>$sum]";
}

//独播函数
function sendMessageByUid($uid, $message)
{
   global $worker;
   if(isset($worker->uidConnections[$uid]))
   {
      $connection = $worker->uidConnections[$uid];
      $connection->send($message);
      return 'ok';
   }
   return 'fail';
}

Worker::runAll();



push_tcp.php文件:

<?php
/**
 * Created by PhpStorm.
 * Date: 2017/10/28
 * Time: 22:29
 */

//建立tcp连接到text连接
$client = stream_socket_client('tcp://127.0.0.1:9988', $errno, $errmsg, 1);

$data = ['type'=>'broadcast', 'data'=>'公告:近期收到站内有恶意诈骗事件,请各位不要相信站内非官方账号的信息'];
//$data = ['type'=>'byUid', 'uid'=>'uid1', 'data'=>'uid1会员您好:近期收到站内有恶意诈骗事件,请不要相信站内非官方账号的信息'];

//写入数据到tcp连接
fwrite($client, json_encode($data)."\n");

//读取连接返回信息
echo fread($client, 6666);



测试流程:


1)广播测试、发送给所有客户端


①守护进程方式启动index.php

blob.png


②打开两个谷歌浏览器的控制台,分别建立 uid1uid2 的websocket连接

var ws = new WebSocket('ws://xx:8888');
ws.onopen = function(){
    var uid = 'uid1';
    ws.send(uid);
};
ws.onmessage = function(e){
    document.body.innerText(e.data);
};

blob.png

blob.png



回车之后可以点击Network看到已经建立了websocket连接了:


blob.png


③执行push_tcp.php推送数据

blob.png


④客户端收到数据

blob.png




2)独播测试,发送消息给指定的uid


需要注释tcp_push.php的广播数据,启用独播,单独发送给uid1

//$data = ['type'=>'broadcast', 'data'=>'公告:近期收到站内有恶意诈骗事件,请各位不要相信站内非官方账号的信息'];
$data = ['type'=>'byUid', 'uid'=>'uid1', 'data'=>'uid1会员您好:近期收到站内有恶意诈骗事件,请不要相信站内非官方账号的信息'];


①、②、③流程同上


④只有uid1的客户端收到消息

blob.png



3)END




代码出自官方手册,本人略作修改


来自ansion博客 

http://www.tp0.top

2017-10-29 11:32:43