使用TP6+Workerman实现私聊(类似QQ)、实时聊天(4、实现实时推送)

8 篇文章 1 订阅
7 篇文章 8 订阅

之前的文章写到了workerman的连接嘛。这次继续之前的,先弄两个页面吧。
在这里插入图片描述

在这里插入图片描述

大概就是弄了这样的两个页面的哈。类似的静态页面啊,网上都会有的。异曲同工的哈。就是把html文件替换成在应用/view/控制器/方法.html
把网上下载的代码放在这个 方法.html
里面。然后把其他所有的文件夹,图片啊,css,js的文件放在public文件夹下就OK了。然后把路径加工一下,最最最简单的方法就是在所有的链接前面加
“/”.像这样,

在这里插入图片描述
好了,继续吧先。
简单说下思路吧。前端连接的时候 可以通过ajax进行绑定user_id和workman为每个用户分配的id。这样就可以实现推送了。贴下我的代码吧。就是简单一个实现。学一学就可以了。实际项目中估计也不会这么用,直接用getwayworker了。

public function onConnect($connection)
    {
        // 生成一个唯一用户的客户端id
        $this->client_id = time().rand(100,999);
        // 将生成的client_id赋给当前连接
        $connection->client_id = $this->client_id;

        // 在当前worker对象中新添属性  保存当前登录的用户的client_id 和 连接对象
        // 以便进行推送
        $this->worker->clientIdConnections[$connection->client_id] = $connection;

        // 将生成的client_id发送给客户端
        $json = [
            'type'  =>  'bind',
            'from'  =>  'worker',
            'to'    =>  $connection->client_id,
            'content' => $this->client_id
        ];
        $connection->send(json_encode($json,true));
    }

这个是前端的代码。给每个用户的user_id和workerman为每个用户分配的id进行绑定 ,这样就可以实现指定用户推送了。

ws = new WebSocket("ws://www.chat.com:2346");
  ws.onopen = function() {
    
  };
  ws.onmessage = function(e) {
      var result = JSON.parse(e.data);
      if (result.type == 'bind') {
         // 请求mvc框架绑定数据
         $.get("<{:url('index/Index/bind')}>"+"?uid="+<{$uid}>+"&client_id="+result.content,function(e){
             if (!e || e.code != 200) {
                alert("连接失败,请重新登录");
                window.location.href = "<{:url('index/Login/index')}>";
             }
         });
      } else if (result.type == 'say') {
         console.log(result);
      }
  };

推送:

public function onMessage($connection, $data)
    {
        $data = json_decode($data,true);
        if ($data["type"] == "say") {
            $result["type"] = "say";
            $result["from"] = $data["from"];
            $result["to"] = $data["to"];
            $result["content"] = $data["content"];
            // dump($this->worker);
            $this->worker->clientIdConnections[$data["to"]]->send(json_encode($result,true));
        }
    }

ajax绑定用户:

public function bind(){
        // 绑定用户和客户端
        $get = Request::get();
        $result["code"] = 200;

        // 检查参数
        if (empty($get['uid']) || empty($get['client_id'])) {
            $result["message"] = "参数错误";
            $result["data"] = [];
            return json($result);
        }

        // 绑定用户session和client_id
        $connectionInfo = [];
        if (Session::has("connectionInfo")) {
            $connectionInfo = Session::get("connectionInfo");
        }
        $connectionInfo[$get["uid"]] = $get["client_id"];
        Session::set("connectionInfo",$connectionInfo);

        $result["code"] = 200;
        $result["message"] = '成功';
        $result["data"] = $connectionInfo;
        return json($result);
    }

整体的效果也没时间弄了。到最后数据是正确的 剩下就是前端的效果了。整体的思路就是将数据库的user_id和workerman为每个用户分配的id进行绑定。绑定后就可以实现指定用户推送了。
到最后也就是一个半成品吧。

{ “from” : 1615112847935 , “to” : 1615112847955 , “content” : “来了老弟” ,
“type” : “say” }

我的数据格式是这样子的,数据格式嘛,怎么来都可以。
前端:

<html>
<head>
<meta charset="utf-8">
<title>双子稚心丶Amor</title>
<link href="/css/style.css" rel="stylesheet" type="text/css">
<script src="/js/jquery.js"></script>
<script src="/js/index.js"></script>
<script src="/js/superslide.2.1.js"></script>
<script src="/js/nicescroll.js"></script>
<script>
  ws = new WebSocket("ws://www.chat.com:2346");
  ws.onopen = function() {
      // console.log("连接成功");
      // JSON.stringify(data);
      // JSON.parse(data);
      // data = { "from" : 1615112847935 , "to" : 1615112847955 , "content" : "来了老弟" , "type" : "say" };
      // console.log(JSON.stringify(data));
      // ws.send(JSON.stringify(data));
  };
  ws.onmessage = function(e) {
      var result = JSON.parse(e.data);
      if (result.type == 'bind') {
         // 请求mvc框架绑定数据
         $.get("<{:url('index/Index/bind')}>"+"?uid="+<{$uid}>+"&client_id="+result.content,function(e){
             if (!e || e.code != 200) {
                alert("连接失败,请重新登录");
                window.location.href = "<{:url('index/Login/index')}>";
             }
         });
      } else if (result.type == 'say') {
         console.log(result);
      }
  };
</script>
</head>
<body style="background-image: url(/images/snow.jpg);background-size: cover;">
<div class="win-bg"><img src="/images/win-bg.png"></div>
<div class="qq" style="display: block;right: 200px;">
  <div class="qq-top">
    <div class="qq-top-icon">
      <i><img src="/images/qq-top.png"></i>
      <span class="qq-top-02 close"><img src="/images/qq-top-02.png"></span>
      <span class="qq-top-01 min"><img src="/images/qq-top-01.png"></span>
    </div>
    <div class="qq-top-name">
      <span><{$memberInfo["uname"]}></span>></span>
      <dl><dd><img src="/images/zai.png"></dd><dt><img src="/images/lv.png"></dt><dt><img src="/images/svip.png"></dt></dl>
    </div>
    <div class="qq-top-shuo"><input type="text" value="这两天空间被各种婚礼刷屏了"></div>
    <div class="qq-top-menu">
      <ul>
        <li></li><li></li><li></li><li></li>
      </ul>
      <span class="qq-top-001"></span>
      <span class="qq-top-002"></span>
    </div>
    <div class="qq-serch">搜索:联系人、讨论组、群、企业</div>
  </div>
  <div class="qq-xuan">
    <ul>
      <li class="qq-xuan-li"><span></span><i></i></li>
      <li><span></span><i></i></li>
      <li><span></span><i></i></li>
      <li><span></span><i></i></li>
    </ul>
  </div>
  <div class="qq-hui">
    <ul>
      {foreach $friendInfo as $key => $item}
      <li>
        <div class="qq-hui-img"><img src="<{$item['head_img']}>"><i></i></div>
        <div class="qq-hui-name"><span><{$item["uname"]}></i></span><i>16:30</i></div>
        <div class="qq-hui-txt" title="">下次我们去公园拍摄吧~[图片]</div>
      </li>
      {/foreach}
    </ul>
  </div>
  <div class="qq-bot">
    <div class="qq-menu">
      <ul>
        <li><img src="/images/bot-menu/01.png"></li>
        <li><img src="/images/bot-menu/02.png"></li>
        <li><img src="/images/bot-menu/03.png"></li>
        <li><img src="/images/bot-menu/04.png"></li>
        <li><img src="/images/bot-menu/05.png"></li>
        <li><img src="/images/bot-menu/06.png"></li>
        <li><img src="/images/bot-menu/07.png"></li>
        <li><img src="/images/bot-menu/08.png"></li>
        <li><img src="/images/bot-menu/09.png"></li>
        <li><img src="/images/bot-menu/10.png"></li>
      </ul>
    </div>
    <div class="qq-bou-she">
      <ul>
        <li><img src="/images/bot-menu/11.png"></li>
        <li><img src="/images/bot-menu/12.png"></li>
        <li><img src="/images/bot-menu/13.png"></li>
        <li><img src="/images/bot-menu/14.png"></li>
        <li><img src="/images/bot-menu/15.png"></li>
        <li><img src="/images/bot-menu/16.png"><span>查找</span></li>
        <li><img src="/images/bot-menu/05.png"><span>应用宝</span></li>
      </ul>
    </div>
  </div>
</div>

<div class="qq-chat">
  <div class="qq-chat-win">
    <ul>
      <li class="she"></li><li class="min"></li><li class="max"></li><li class="close"></li>
    </ul>
  </div>
  <div class="qq-chat-top">
    <div class="qq-chat-tops">
      <div class="qq-chat-t-head"><img src=""></div>
      <div class="qq-chat-t-name"></div>
      <div class="qq-chat-t-shuo">站在别人的雨季,淋湿自己空弹一出戏.....</div>
    </div>
    <div class="qq-chat-menu">
      <ul>
        <li><span><img src="/images/chat/icon-01.png"></span></li>
        <li><span><img src="/images/chat/icon-02.png"></span></li>
        <li><span><img src="/images/chat/icon-03.png"></span><i></i></li>
        <li><span><img src="/images/chat/icon-04.png"></span><i></i></li>
        <li><span><img src="/images/chat/icon-05.png"></span><i></i></li>
        <li><span><img src="/images/chat/icon-06.png"></span></li>
        <li><span><img src="/images/chat/icon-07.png"></span><i></i></li>
      </ul>
    </div>
  </div>
  <div class="qq-chat-bot">
    <div class="qq-chat-txt">
      <ul>
        <li>
          <div class="qq-chat-you blue"><span></span><i></i></div>
          <div class="qq-chat-ner">在么?找你有点事</div>
        </li>
      </ul>
    </div>
    <div class="qq-chat-text">
      <ul>
        <li><span><img src="/images/chat/menu-01.png"></span></li>
        <li><span><img src="/images/chat/menu-02.png"></span></li>
        <li><span><img src="/images/chat/menu-03.png"></span></li>
        <li><span><img src="/images/chat/menu-04.png"></span></li>
        <li><span><img src="/images/chat/menu-05.png"></span><i></i></li>
        <li><span><img src="/images/chat/menu-06.png"></span></li>
        <li><span><img src="/images/chat/menu-07.png"></span><i></i></li>
        <li><span><img src="/images/chat/menu-08.png"></span></li>
        <li><span><img src="/images/chat/menu-09.png"></span><i></i></li>
        <li class="fr" style="margin-right:5px;"><span><img src="/images/chat/menu-10.png"></span><p>消息记录</p><i></i></li>
      </ul>
      <textarea id="qq-chat-text"></textarea>
      <div class="qq-chat-but">
        <span class="fasong">发送(S)</span>
        <span class="close-chat">关闭(C)</span>
      </div>
    </div>
  </div>
</div>
</body>
</html>

控制器:

<?php
namespace app\index\controller;

use think\facade\View;
use app\BaseController;
use think\worker\Server;
use think\facade\Session;
use app\index\model\Memberfriend;
use app\index\model\Member;
use think\facade\Request;

class Index extends BaseController{
    public function index(){
        // 检查是否登录
        if (!Session::has("user_id")) {
            redirect(url("index/Login/index"))->send();
        }
        $user_id = Session::get("user_id");
        $this->uid = $user_id;
        trace("index");
        $memberInfo = Member::find($user_id);

        // 获取好友列表
        $friend_rt = Memberfriend::getMembers($user_id)->toArray();
        $friend = explode(",",$friend_rt['user_friend']);

        // 获取好友列表信息
        $friendInfo_rt = Member::getMemberInfo([["id","in",$friend]])->toArray();
        foreach ($friendInfo_rt as $key => $value) {
            $friendInfo[$value['id']] = $value;
        }
        
        // 渲染到页面
        View::assign([
            'friendInfo' => $friendInfo,
            'memberInfo' => $memberInfo,
            'uid'        => $user_id
        ]);
        return View::fetch();
    }

    public function bind(){
        // 绑定用户和客户端
        $get = Request::get();
        $result["code"] = 200;

        // 检查参数
        if (empty($get['uid']) || empty($get['client_id'])) {
            $result["message"] = "参数错误";
            $result["data"] = [];
            return json($result);
        }

        // 绑定用户session和client_id
        $connectionInfo = [];
        if (Session::has("connectionInfo")) {
            $connectionInfo = Session::get("connectionInfo");
        }
        $connectionInfo[$get["uid"]] = $get["client_id"];
        Session::set("connectionInfo",$connectionInfo);

        $result["code"] = 200;
        $result["message"] = '成功';
        $result["data"] = $connectionInfo;
        return json($result);
    }
}

worker类:

<?php
namespace app\index\controller;

use think\facade\View;
use think\worker\Server;
use think\facade\Session;
use GatewayClient\Gateway;

// require_once '../vendor/autoload.php';
// use app\index\model\Memberfriend;
// use app\index\model\Member;

class Worker extends Server{

    // json消息格式{
    //      type : say--发送的消息 bind--用户连接绑定client_id
    //      from : 谁发的
    //      to   : 给谁发的
    //      content : '发的内容'
    // }

    protected $socket = 'websocket://www.chat.com:2346';

    protected $client_id;

    public function onMessage($connection, $data)
    {
        $data = json_decode($data,true);
        if ($data["type"] == "say") {
            $result["type"] = "say";
            $result["from"] = $data["from"];
            $result["to"] = $data["to"];
            $result["content"] = $data["content"];
            // dump($this->worker);
            $this->worker->clientIdConnections[$data["to"]]->send(json_encode($result,true));
        }
        // $json = [
        //     'type'  =>  'say',
        //     'from'  =>  '1615112847955',
        //     'to'    =>  $connection->client_id,
        //     'content' => $data["content"]
        // ];
        // $connection->send(json_encode($json,true));
    }

    /**
     * 当连接建立时触发的回调函数
     * @param $connection
     */
    public function onConnect($connection)
    {
        // 生成一个唯一用户的客户端id
        $this->client_id = time().rand(100,999);
        // 将生成的client_id赋给当前连接
        $connection->client_id = $this->client_id;

        // 在当前worker对象中新添属性  保存当前登录的用户的client_id 和 连接对象
        // 以便进行推送
        $this->worker->clientIdConnections[$connection->client_id] = $connection;

        // 将生成的client_id发送给客户端
        $json = [
            'type'  =>  'bind',
            'from'  =>  'worker',
            'to'    =>  $connection->client_id,
            'content' => $this->client_id
        ];
        $connection->send(json_encode($json,true));
    }

    /**
     * 当连接断开时触发的回调函数
     * @param $connection
     */
    public function onClose($connection)
    {
        
    }

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

    /**
     * 每个进程启动
     * @param $worker
     */
    public function onWorkerStart($worker)
    {

    }
    
}

这是代码:https://gitee.com/zqy-904915452/tp6-workerman-chat

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
ThinkPHP 6 中使用 Workerman 实现定时器可以通过添加自定义命令来实现。下面是一个简单的实现步骤: 1. 首先,确保你已经安装了 Workerman 和 think-worker 扩展。可以通过执行以下命令来安装它们: ``` composer require workerman/workerman think-worker ``` 2. 创建一个自定义的命令类来处理定时任务。在 app/command 目录下创建一个名为 Timer.php 的文件,并在该文件中编写以下代码: ```php <?php namespace app\command; use think\console\Command; use think\console\Input; use think\console\Output; class Timer extends Command { protected function configure() { $this->setName('timer:work')->setDescription('Workerman Timer'); } protected function execute(Input $input, Output $output) { $worker = new \Workerman\Worker(); $worker->onWorkerStart = function($worker) { // 在这里编写定时任务的处理逻辑 \Workerman\Lib\Timer::add(1, function() { echo "定时任务执行\n"; }); }; \Workerman\Worker::runAll(); } } ``` 3. 注册自定义命令。在 config/console.php 中的 commands 数组中添加命令类的命名空间路径: ```php 'commands' => [ 'app\command\Timer', ], ``` 4. 运行定时任务。通过执行以下命令来运行定时任务: ``` php think timer:work ``` 这样,定时任务就会在后台运行,并每秒钟执行一次。你可以在 `$worker->onWorkerStart` 回调函数中编写具体的定时任务逻辑。请根据自己的需求进行修改和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值