TP使用workerman小程序通信

分类首页小程序日期1年前访问539评论0

第一步:

Linux环境检查脚本

Linux用户可以运行以下脚本检查本地环境是否满足WorkerMan要求

curl -Ss https://www.workerman.net/check | php

如果脚本中全部提示ok,则代表满足WorkerMan运行环境

(注意:检测脚本中没有检测event扩展,如果并发连接数大于1024建议安装event扩展)

第二步:

Composer安装:

composer require workerman/workerman


第三步

服务端代码(里面有一些是我自己业务的逻辑代码,不要全部复制粘贴使用)


<?php

namespace app\api\controller\v1;

use Workerman\Worker;
use app\common\controller\Api;
use app\common\library\Auth;
/**
 * 接口
 */
class Weekly extends Api
{
    protected $noNeedLogin = ['*'];
    protected $noNeedRight = ['openai'];
    protected $auth = null;
    protected $worker = null;
    protected $userId = 0;
 
    public function index(){
        $this->auth = Auth::instance();
         // 创建一个Worker监听9090端口,使用http协议通讯
        $worker = new Worker("websocket://0.0.0.0:9090");
        $this->worker = $worker;
         // 启动4个进程对外提供服务
        $worker->count = 4;
        $worker->uidConnections = array();
        $worker->onConnect = function ($connection){
            print_r('第一次!');
        };
        // 接收到浏览器发送的数据时回复hello world给浏览器
        //$http_worker->onMessage = function(TcpConnection $connection, Request $request)
        $worker->onMessage = function ($connection,  $request) use ($worker) {
            // print_r($connection);
            // foreach ($http_worker->connections as $connection) {
        
            //     $connection->send($request);
            // }
            $data = json_decode($request,true);
            if(empty($data['token'])){
                return;
            }
            $token = $data['token'];
            //初始化
            $this->auth->init($token);
            $userinfoId = 0;
            //检测是否登录
            if (!$this->auth->isLogin()) {
                print_r('没登录');
                return;
            }
            // 判断当前客户端是否已经验证,既是否设置了uid
            if (!isset($connection->uid)) {
                 print_r('登录');
                $userinfo = $this->auth->getUserinfo();
                $userinfoId = $userinfo['id'];
                $this->userId = $userinfoId;
                // 没验证的话把第一个包当做uid(这里为了方便演示,没做真正的验证)
                $connection->uid = $userinfoId;
                /* 保存uid到connection的映射,这样可以方便的通过uid查找connection,
                * 实现针对特定uid推送数据
                */
                print_r('用户uid:'.$connection->uid . '\n');
        
                $worker->uidConnections[$connection->uid] = $connection;
                // return;
            }
           $this->worker = $worker;
           if(!empty($data['type'])&&$data['type']='openai'){
              
            //   print_r($data['type']);
                $this->openai($data['data']['keyword'],$data['data']['wordNum'],$data['data']['type'],$data['data']['occupation']);
            }
            // $this->sendMessageByUid($worker, 2, 'hello world' . time());
            // 向浏览器发送hello world
            //$connection->send('hello world'.time());
        };
        // 当有客户端连接断开时
        $worker->onClose = function ($connection) {
            if (isset($connection->uid)) {
                // 连接断开时删除映射
                print_r('有用户断开:'.$connection->uid);
                unset($this->worker->uidConnections[$connection->uid]);
            }
        };
        Worker::runAll();
    }
    // 针对uid推送数据
    private function sendMessageByUid($worker, $uid, $message,$expand=[])
    {
        
        if (isset($worker->uidConnections[$uid])) {
             
            //print_r($worker->uidConnections[$uid] . ',发送个指定用户\n');
            $connection = $worker->uidConnections[$uid];
            $content = ['content'=>$message];
            $data = [
                'code'=>1,
                'data'=>array_merge($expand,$content)
            ];
            $connection->send(json_encode($data,true));
            return true;
        }else{
             print_r('没触发');
            return false;
        }
       
    }
    /**
     * $num 生成字数
     * $type 生成类型
     * $occupation 职业
     * $keyword 关键词
     */
    private function openai($keyword='',$num= '',$type='周报',$occupation=''){
        
        if($num){
            $num = '编写'.$num.'字';
        }else{
           $num = '把以下'; 
        }
        if($occupation){
            $occupation = '软件开发专业';
        }
       $data = json_encode(['prompt'=>'请帮我'.$num.'的工作内容填充为一篇完整'.$occupation.'的'.$type.',用 markdown 格式以分点叙述的形式输出:'.$keyword]);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
         curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
            curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_URL, "https://xxxx.com" );
        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);    
        curl_setopt($ch, CURLOPT_NOPROGRESS, FALSE);    
        curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, array($this, 'apicallback'));  
        $result = curl_exec($ch); //***Note A***
        curl_close($ch);
        // print_r($result);
        
        $this->sendMessageByUid($this->worker, $this->userId, '',['status'=>1]);
    }
      private function apicallback($clientp, $dltotal, $dlNow, $ultotal, $ulNow) {
        // $contents = fread($clientp,"1");
        $this->sendMessageByUid($this->worker, $this->userId, curl_multi_getcontent ($clientp),['status'=>0]);
        // echo (curl_multi_getcontent ($clientp)).'/';
        
    }
}


第四步

在项目根目录创建一个server.php文件用于启动workerman
代码如下:



<?php
define('APP_PATH', __DIR__ . '/application/');
define('BIND_MODULE','api/v1/Weekly');//这个路径根据自己项目目录修改
// 加载框架引导文件
require __DIR__ . '/thinkphp/start.php';


第五步

在服务器终端启动workerman
php server.php index start



小程序端

连接,小程序必须使用wss(sll)连接,使用服务器域名转发

uni.connectSocket({
			  url: 'wss://v.zmmz.com/wss'
			});
连接成功
uni.onSocketOpen(function (res) { console.log('WebSocket连接已打开!');
			  uni.sendSocketMessage({
				data: JSON.stringify({token:userInfo.token})
			  });
			});
接收消息
uni.onSocketMessage(function (res) {
	console.log(res.data)			
});
发送消息
uni.sendSocketMessage({
	data: JSON.stringify({token:t.userInfo.token,type:'openai',data:{keyword:t.keyword,wordNum:t.array[t.index],type:t.type,occupation:t.occupation}})
});

nginx转发

  #此处是重点代理wss协议输出
    location /wss
    {
      proxy_pass http://127.0.0.1:端口;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "Upgrade";
      proxy_set_header X-Real-IP $remote_addr;
    }