第一步:cmd 到项目根目录运行
1 :composer require topthink/think-worker=1.0.* -vvv

windows下需要运行(tp5手册:https://www.kancloud.cn/manual/thinkphp5/235128)

2: composer require workerman/workerman-for-win
第二步
tp 、fastadmin 框架 public 新建启动文件server.php

<?php
define('APP_PATH', __DIR__ . '/../application/');
define('BIND_MODULE','worker/Worker');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';

第三步
application下新建worker目录及worker.php文件
worker.php文件内容如下


<?php
namespace app\worker\controller;
use think\worker\Server;
use Workerman\Lib\Timer;
class Worker extends Server
{
    protected $socket = 'websocket://0.0.0.0:2346';
    protected $processes = 1;//进程数
    protected $worker; 
    protected $HEARTBEAT_TIME = '60';//心跳时间,后端主动关闭客户端
    public function __construct()
    {
        parent::__construct();
        $this->worker->uidConnections = array(); //用户链接池 存储映射
    }

    /**
     * 接收消息
     * @param $connection
     * @param $data
     */
    public function onMessage($connection, $data)
    {
        //客户端与后端消息链接唯一标识
        $uid = $connection->uid;
        if($uid) {
            $data=json_decode($data,true);
            $message=['code'=>0,'msg'=>'你还活着','type'=>0,'data'=>[]];
            if(!$data){
                return true;
            }
            //区分各种业务处理
            $method = $data['method'];
            $is_push=0;//是否主动推送消息
            switch ($method) {
                //创建聊天室
                case 'add_chat':
                    $is_push=1;//开启推送
                    $chat_id=1111;//你的聊天室id 返回给前端
                    $message=['code'=>0,'msg'=>'创建成功','type'=>-1,'data'=>$chat_id];
                    break;
                //发送消息
                case 'send':
                    $is_push=1;//开启推送
                    $message='你处理的消息信息';
                    
                    //如果对方在线 向对方发送一条消息
                    $this->sendMessageByUid($data['user_id'],$message);
                    
                    $message2=‘聊天消息列表';
                    //对方在线 更新对方消息接收列表(没做分页处理,分页后台发送单条信息前端使用push)
                    $this->sendMessageByUid($data['user_id'],$message2);
                    
                    break;
                 //客户端主动来取消息列表
                case 'list':    
                    $is_push=1;//开启推送
                    $message=‘聊天消息列表';
                    break;
                //客户端主动取聊天室内容
                case 'chat_list':
                    $is_push=1;//开启推送
                    $post=[
                        'user_id'=>$uid,
                        'chat_id'=>$data['chat_id'],//聊天室id
                        'page'=>$data['page'],//分页数
                    ];
                    $message=ChatList::getList($post);
                    break;
            }
           //向自己推送消息
            if($is_push){
                $this->sendMessageByUid($uid,$message);
            }
        }else{//查询不到用户信息,关闭此连接
            $this->onClose($connection);
        }
    }
    // 向所有验证的用户推送数据
    function broadcast($message)
    {
        foreach($this->worker->uidConnections as $connection)
        {
            $connection->send($message);
        }
    }

    // 针对uid推送数据
    function sendMessageByUid($uid, $message)
    {

        if(isset($this->worker->uidConnections[$uid]))
        {
            $connection = $this->worker->uidConnections[$uid];
            $connection->send(json_encode($message,true));
        }
    }

    /**
     * 当连接建立时触发的回调函数
     * @param $connection
     */
    public function onConnect($connection)
    {
        $connection->onWebSocketConnect = function($connection , $http_header)
        {
            // 可以在这里判断连接来源是否合法,不合法就关掉连接
            // $_SERVER['HTTP_ORIGIN']标识来自哪个站点的页面发起的websocket连接
            $arr_request=[
                '域名1',
                '域名2',
            ];
            //判断是否合法连接
            if(in_array( http_header['Host'],$arr_request) !=true)
            {
                $connection->close();
            }
            // 存客户端与websocket的映射,唯一连接标识(!!!关键)
            if(!isset($connection->uid))
            {
                $connection->uid = $_SERVER['HTTP_TOKEN'];
                $this->worker->uidConnections[$connection->uid]=$connection;
                return;
            }
        };
    }

    /**
     * 当连接断开时触发的回调函数
     * @param $connection
     */
    public function onClose($connection)
    {
//        //代表用户下线,清除用户信息
        if(isset($connection->uid))
        {
            // 连接断开时删除映射
            unset($this->worker->uidConnections[$connection->uid]);
        }
    }

    /**
     * 当客户端的连接上发生错误时触发
     * @param $connection
     * @param $code
     * @param $msg
     */
    public function onError($connection, $code, $msg)
    {
        echo "error $code $msg\n";
    }

    /**
     * 每个进程启动
     * @param $worker
     */
    public function onWorkerStart($worker)
    {
        //每10秒检查一下客户端是否还连着服务端。超时未相应也会主动关闭与客户端的连接
        Timer::add(10, function()use($worker){
            $time_now = time();
            foreach($worker->connections as $connection) {
                // 有可能该connection还没收到过消息,则lastMessageTime设置为当前时间
                if (empty($connection->lastMessageTime)) {
                    $connection->lastMessageTime = $time_now;
                    continue;
                }
                $diff_time = $time_now - $connection->lastMessageTime;
                $msg = '距离上次通话已经过去'.$diff_time.'秒';
                $message=['code'=>0,'msg'=>$msg,'type'=>0,'data'=>[]];
                $connection->send(json_encode($message,true));
                // 上次通讯时间间隔大于心跳间隔,则认为客户端已经下线,关闭连接
                if ($time_now - $connection->lastMessageTime > $this->HEARTBEAT_TIME) {
                          $connection->close();
                }
            }
        });
    }
}

cmd 项目中到public目录下运行php server.php start -测试环境 生产环境 后面加-d

第三步 浏览器:
浏览器打开项目运行 console

ws = new WebSocket(“ws://127.0.0.1:3344”);
ws.onopen = function() {undefined
alert(“连接成功”);
ws.send(‘tom’);
alert(“给服务端发送一个字符串:tom”);
};
ws.onmessage = function(e) {undefined
alert(“收到服务端的消息:” + e.data);
};
ƒ (e) {undefined
alert(“收到服务端的消息:” + e.data);
}

Logo

电影级数字人,免显卡端渲染SDK,十行代码即可调用,工业级demo免费开源下载!

更多推荐