THINKPHP5.1在windows系统下,安装GateWayWorker

2023-11-04

一、GateWayWorker简单介绍:
a)、GatewayWorker基于Workerman开发的一个项目框架,用于快速开发TCP长连接应用,例如app推送服务端、即时IM服务端、游戏服务端、物联网、智能家居等等;
b)、如果你的项目是长连接并且需要客户端与客户端之间通讯,建议使用GatewayWorker。
短连接或者不需要客户端与客户端之间通讯的项目建议使用Workerman。
GatewayWorker不支持UDP监听,所以UDP服务请选择Workerman。
如果你是一个有多进程socket编程经验的人,喜欢定制自己的进程模型,可以选择Workerman。

二、GatewayClient安装
按照手册下载地址:https://github.com/walkor/GatewayClient
你也可以拿我的压缩包:百度网盘,提取码:4ewq
下载完成后你可以放在THINKPHP框架的extend目录,为了方便开发:
在这里插入图片描述
三、结合THINKPHP框架开发:
参照手册:http://doc2.workerman.net/work-with-other-frameworks.html
在Events.php下直接上现成的测试代码(注意:仅供参考)

<?php
/**
 * This file is part of workerman.
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the MIT-LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @author walkor<walkor@workerman.net>
 * @copyright walkor<walkor@workerman.net>
 * @link http://www.workerman.net/
 * @license http://www.opensource.org/licenses/mit-license.php MIT License
 */

/**
 * 用于检测业务代码死循环或者长时间阻塞等问题
 * 如果发现业务卡死,可以将下面declare打开(去掉//注释),并执行php start.php reload
 * 然后观察一段时间workerman.log看是否有process_timeout异常
 */

use \GatewayWorker\Lib\Gateway;

/**
 * 主逻辑
 * 主要是处理 onConnect onMessage onClose 三个方法
 * onConnect 和 onClose 如果不需要可以不用实现并删除
 */
class Events
{
    /**
     * 当客户端连接时触发
     * 如果业务不需此回调可以删除onConnect
     * 
     * @param int $client_id 连接id
     */
    public static function onConnect($client_id)
    {
        Gateway::sendToClient($client_id, json_encode([
            'type'=>'init',//客户连接后向用户发送绑定uid请求(1)
            'client_id'=>$client_id
        ]));

        // 向当前client_id发送数据
//        Gateway::sendToClient($client_id, "Hello $client_id\r\n");
        // 向所有人发送
//        Gateway::sendToAll("$client_id login\r\n");
    }
    
   /**
    * 当客户端发来消息时触发
    * @param int $client_id 连接id
    * @param mixed $message 具体消息
    */
   public static function onMessage($client_id, $message)
   {
        // 向所有人发送 
//        Gateway::sendToAll("$client_id said $message\r\n");

       $message_data = json_decode($message,true);
       if(!$message_data){
           return;
       }

       switch ($message_data['type']) {
           case "say":
               $content = $message_data['data'];
               $fromid = $message_data['fromid'];
               $toid = $message_data['toid'];
               $infotype = $message_data['infotype'];
               $data = [
                   'type' => 'answer',
                   'id' => $client_id,
                   'fromid' =>$fromid,
                   'toid' => $toid,
                   'time' => time(),
                   'data' => $content,
                   'infotype' => $infotype
               ];

               if(Gateway::isUidOnline($toid)){//判断用户是否在线
                   $data['isread'] = 1;
                   file_put_contents(__DIR__.'/123.txt',json_encode($data));
                   Gateway::sendToUid($toid, json_encode($data));//向指定用户发送信息
               }else{
                   $data['isread'] = 0;
                   $data['type'] = 'save';
                   file_put_contents(__DIR__.'/1234.txt',json_encode($data));
                   Gateway::sendToUid($fromid,json_encode($data));//向指定用户发送信息
               }
               break;
           case "bind":
               /*接收到客户端发来的uid后进行绑定(3)*/
               $uid = $message_data['fromid'];
               Gateway::bindUid($client_id,$uid);//将client_id与uid进行绑定
               break;
           case "pong":
               return ;//心跳检测
               break;
       }
   }
   
   /**
    * 当用户断开连接时触发
    * @param int $client_id 连接id
    */
   public static function onClose($client_id)
   {
       // 向所有人发送 
//       GateWay::sendToAll("$client_id logout\r\n");
   }
}


前端代码(仅供参考):
注意:文件位置在你的项目地址\application\index\view\index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        #talk{
            width:370px;
            list-style-type:none;
        }
        #talk .right{
            text-align: left;
        }
        #talk .left{
            text-align: right;
        }
        .regi_box{
            width:250px;
            border:1px solid #000;
            padding:10px;
            box-sizing: border-box;
        }
        .regi_box .sub,.regi_box .sub2{
            width:100%;
            text-align: center;
            color:#fff;
            background:#ff5555;
            margin-top:10px;
            padding:5px;
            box-sizing: border-box;
            border-radius: 7px;
            cursor: pointer;
        }
        .out{
            padding:2px 4px;
            border-radius: 7px;
            background:#ff5555;
            color:#fff;
            cursor:pointer;
            width:fit-content;
        }
    </style>
</head>
<body>
{if ($user['id']==0 || $user['id']=='')}
    <!--<div class="regi_box">
        <div class="register">注册会员</div>
        <label for="nickname">昵称:</label><input type="text" id="nickname" name="nickname" value="">
        <div class="sub">注册</div>
    </div>-->
    <div class="regi_box">
        <div class="register">登录</div>
        <label for="uid">ID:</label><input type="text" id="uid" name="id" value="">
        <div class="sub2">登录</div>
    </div>
{else}
    您已登录,{$user['nickname']},IP:{$user['client_ip']}
    <div class="out">退出</div>
{/if}

<div class="panel panel-default panel-intro">
    <input type="hidden" id="uid" value="{$uid}">
    <div class="main wrap">
        <ul id="talk" class="wrap">
            {foreach name="list" item="vo"}

            {if $vo.uid!=$user['id']}
                <!--我的发送-->
                {if $vo.info_type==1}
                <li class="right"><p>{$vo.content}</p></li>
                {else}
                <li class="right"><img src="{$vo.content}" style="width:100px;height:100px;"></li>
                {/if}
            {else}
                <!--对方发送-->
                {if $vo.info_type==1}
                <li class="left"><p>{$vo.content}</p></li>
                {else}
                <li class="left"><img src="{$vo.content}" style="width:100px;height:100px;"></li>
                {/if}
            {/if}
            {/foreach}
        </ul>
    </div>

    <div class="comment">
        <textarea id="comment" class="form-control editor" rows="1" name="comment" cols="50"></textarea>
        <input type="file" name="pic" id="file" style="display:none">
        <span id="pic">图片</span>
        <button type="button" class="butt send-btn">发送</button>
    </div>
</div>

</body>
<script src="__JS__/jquery-1.11.3.min.js"></script>
<script type="text/javascript">
    $('.sub').click(function(){
        let nickname = $('#nickname').val();
        if(nickname==''){
            alert('请填写昵称!');
        }
       $.ajax({
           url:'/register',
           dataType:'json',
           data:{
             nickname:nickname
           },
           type:'post',
           success:function(res){
               alert('登录成功');
               setTimeout(function(){
                   window.location.reload();
               },1000)
           }
       })
    });
    $('.sub2').click(function(){
        let id = $('#uid').val();
        if(id==''){
            alert('请填写ID号!');
        }
        $.ajax({
            url:'/login',
            dataType:'json',
            data:{
                id:id
            },
            type:'post',
            success:function(res){
                alert('登录成功');
                setTimeout(function(){
                    window.location.reload();
                },1000)
            }
        })
    });
    $('.out').click(function(){
        $.ajax({
            url:'/out',
            dataType:'json',
            data:{
            },
            type:'post',
            success:function(res){
                alert('退出登录成功');
                setTimeout(function(){
                    window.location.reload();
                },1000)
            }
        })
    });

    var fromid = {$user['id']==''?0:$user['id']};
    var toid = 1;//登录ID1时这里修改2,登录ID2时这里修改1。
    var ws = new WebSocket("ws://127.0.0.1:8282");
    var msg = '{"type":"bind","fromid":"'+fromid+'"}';
    // send();

    ws.onmessage = function(e){
        ws.send(msg);
        // var message = e;
        var message2 = jQuery.parseJSON(e.data);
        console.log('message2',e,message2);
        // var message = eval("("+e.data+")");
        switch(message2.type){
            case "answer" :
                if(toid==message2.fromid){
                    var html = '';
                    if(message2.infotype=='1'){
                        html += '<li class=\"right\">'+'<p>'+message2.data+'</p>'+'</li>';
                    }else{
                        html += '<li class=\"right\"><img src=\"'+message2.data+'\" style="width:100px;height:100px;"></li>';
                    }

                    $("#talk").append(html);
                    message2.type = '1';
                    send(message2);
                }
                break;
            case "init" :
                var bind = '{"type":"bind","fromid":"'+fromid+'"}';
                ws.send(bind);/*接收到服务端发来的绑定uid请求,将uid发送至服务端进行绑定(2)*/
                break;
            case "ping" :
                var pong = '{"type":"pong","fromid":"'+fromid+'"}';
                break;
            case "save" :
                if(message2.fromid==fromid){
                    message2.fromid = toid;
                    message2.type='2';
                    send(message2);
                }
                break;
        }
    };
    $(".send-btn").click(function() {
        var message = $("#comment").val();
        var html = '';
        html += '<li class=\"left\">'+'<p>'+message+'</p>'+'</li>';
        $("#talk").append(html);
        $("#comment").val("");
        var msg = '{"type":"say","infotype":"1","data":"'+message+'","fromid":"'+fromid+'","toid":"'+toid+'"}';
        // send();
        if(fromid=='' || fromid==0){
            alert('请先登录');return;
        }
        ws.send(msg);

    });
    function send(message){
        var uid = message.fromid;
        var content = message.data;
        var time = message.time;
        var isread = message.isread;
        var toid = message.toid;

        // url('index/message/talk')
        $.ajax({
            url: "/talk",
            type: 'POST',
            dataType: 'json',
            data: {
                'uid' : uid,
                'content' : content,
                'time' : time,
                'isread' : isread,
                'type':message.type,
                'info_type':message.infotype,
                'toid':toid,
            }
        })
    }

    $(document).ready(function(){
        $('#talk').scrollTop( $('#talk')[0].scrollHeight );
    });

    $("#pic").click(function() {
        $("#file").click();
    });
    $("#file").change(function() {
        fromdata = new FormData();
        fromdata.append('file',$("#file")[0].files[0]);
        $.ajax({
            url: "{:url('vilage/message/upload')}",
            type: 'post',
            dataType: 'json',
            data: fromdata,
            processData:false,
            contentType:false,
            success:function(res){
                console.log(res);
                res = JSON.parse(res);
                console.log(res);
                if(res.code==1)
                {
                    var domain = window.location.host;
                    var imgurl = 'http://' + domain + res.url;
                    var msg  = '{"type":"say","infotype":"2","infotype":"2","data":"'+imgurl+'","fromid":"'+fromid+'","toid":"'+toid+'"}';
                    var html = '';
                    html += '<li class=\"left\"><img src=\"'+imgurl+'\" style="width:100px;height:100px;"></li>';
                    $("#talk").append(html);
                    $(".chat-content").append(html);

                    ws.send(msg);
                }else{
                    alert(res.msg);
                }
            }
        })

    });

</script>
</html>

bind.php(处理发送消息记录数据库操作、登录、注册、注销的文件)仅供参考:
注意:文件位置在你的项目地址\application\index\controller\bind.php

<?php
namespace app\index\controller;
use GatewayClient\Gateway;
use think\Db;

class Bind extends Base{
    public function index(){
        $get = input();

        $data = json_decode($get['data']);
//        echo json_encode(array('data'=>$data));exit;

        //加载GatewayClient。关于GatewayClient参见本页面底部介绍
//        require_once '/vendor/workerman/gatewayClient/Gateway.php';
        // GatewayClient 3.0.0版本开始要使用命名空间

        // 设置GatewayWorker服务的Register服务ip和端口,请根据实际情况改成实际值(ip不能是0.0.0.0)
        Gateway::$registerAddress = '127.0.0.4:1236';

        // 假设用户已经登录,用户uid和群组id在session中
//        $_SESSION['uid']
        $uid      = $data['user'];
        $group_id = $_SESSION['group'];
        // client_id与uid绑定
        Gateway::bindUid($client_id, $uid);
        // 加入某个群组(可调用多次加入多个群组)
        Gateway::joinGroup($client_id, $group_id);
    }

    public function talk(){
        $get = input();
//        print_r($get);die;
        $res = Db::name('talklog')->insert(array(
            'uid'=>$get['uid'],
            'content'=>$get['content'],
            'time'=>$get['time'],
            'isread'=>$get['isread'],
            'type'=>$get['type'],
            'info_type'=>$get['info_type'],
            'toid'=>$get['toid'],
            'message_type'=>$get['message_type']==''?0:$get['message_type']
        ));
    }

    public function register(){
        $get = input();

        $data['client_ip'] = $_SERVER['REMOTE_ADDR'];
        $data['nickname'] = trim($get['nickname']);
        $data['time'] = time();

        $res = Db::name('talkuser')->insert($data);

        if($res){
            echo 1;exit;
        }
    }
    public function out(){
        unset($_SESSION['user']);
        echo 1;exit;
    }
    public function login(){
        $get = input();

        $user = Db::name('talkuser')->where('id',$get['id'])->find();
        if($user){
            $_SESSION['user'] = $user;
            echo 1;exit;
        }
    }
}

index.php,代码如下(仅供测试):
注意:文件位置在你的项目地址\application\index\controller\index.php

<?php

namespace app\index\controller;

use think\Controller;
use think\Config;
use think\Db;
use think\cache\driver\Redis;
//use Workerman\Worker;

class Index extends Base
{
    public function index()
    {
        //测试,2021、05、08
        //获取会员
        $user = Db::name('talkuser')->where('id',$_SESSION['user']['id'])->find();
        //获取聊天记录
        $list = Db::name('talklog')->order('time asc')->select();
        
        $this->assign('user',$user);
        $this->assign('list', $list);
        return $this->fetch('/index');
    }
}

然后找到start_gateway.php,修改协议及端口(websocket://0.0.0.0:8282):
在这里插入图片描述

四、GateWayworker的启动与停止:
在windows系统下直接点击运行 “start_for_win.bat” 文件即可:
在这里插入图片描述
在这里插入图片描述
注意:如果启动失败,则找你现在php版本的PHP.ini文件找到disabled_function删除proc_open函数

五、windows系统下需要开启telnet(跟着我的截图走):
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
打开telnet后,在cmd命令行输入telnet 127.0.0.1 8282然后回车:
在这里插入图片描述
注意:这两个窗口不能关掉

简易聊天室成品图:
在这里插入图片描述
六、数据表设计图:
在这里插入图片描述
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

THINKPHP5.1在windows系统下,安装GateWayWorker 的相关文章

随机推荐

  • mysql group by 中文_MySQL GROUP BY 语句

    MySQL GROUP BY 语句 GROUP BY 语句根据一个或多个列对结果集进行分组 在分组的列上我们可以使用 COUNT SUM AVG 等函数 GROUP BY 语法 SELECT column name function col
  • 单片机学习 1-LED灯的点亮(全操作)

    LED灯 P0 P1 P2 P3结构图 除了P0端口需要自己外接上拉电阻 否则只能输入输出低电平 其它自带上拉电阻 因此都可以实现高低电平的输入输出 LED灯介绍 LED灯本质是发光二极管 单片机输入电流控制在3mA 20mA之间 可串联电
  • ubuntu pycharm 无法输入中文

    很多人反馈是和ubuntu20 04有关 但是其实应该是和pycharm20 2 3有关 只需要替换掉版本里面的jbr即可 1 下载jbr https confluence jetbrains com pages viewpage acti
  • 数组-第三大的数

    题意 给定一个非空数组 返回此数组中第三大的数 如果不存在 则返回数组中最大的数 要求算法时间复杂度必须是O n 示例 1 输入 3 2 1 输出 1 解释 第三大的数是 1 示例 2 输入 1 2 输出 2 解释 第三大的数不存在 所以返
  • 笔记本电脑运行特别慢怎么解决

    其实不管是笔记本电脑还是台式电脑 用久了肯定多多少少都会有点卡顿的情况出现 很多人的笔记本就是用久了就有这种情况 面对这种情况 如果大家想快速的解决问题 就一起学学今天的关于笔记本电脑运行特别慢怎么解决的内容吧 工具 原料 系统版本 win
  • 操作系统fork()进程

    1 fork 是创建进程函数 2 c程序一开始 就会产生 一个进程 当这个进程执行到fork 的时候 会创建一个子进程 3 此时父进程和子进程是共存的 它们俩会一起向下执行c程序的代码 4 需要注意 子进程创建成功后 fork是返回两个值
  • C语言—星空&下雪特效(Easyx)

    目录 实现效果如图 01 星空 静态 02 下雪 动态 实现效果如图 01 星空 静态 include
  • [C++11]std::promise

    一 std promise介绍 std promise 是C 11并发编程中常用的一个类 常配合std future使用 其作用是在一个线程t1中保存一个类型typename T的值 可供相绑定的std future对象在另一线程t2中获取
  • vue click.stop 阻止点击事件继续传播(阻止事件冒泡)

    场景 H5 移动端 弹窗表单 背景是遮罩 点击表单外遮罩时关闭弹窗 点击表单则不关闭弹窗 click stop 阻止点击事件继续传播
  • 进阶指针【指针的进阶使用方法】

    进阶指针目录 前言 字符指针 指向字符 指向字符串常量 指向同一个字符串常量的字符指针 指针数组 指针数组的定义和使用 数组指针 数组指针的定义 数组指针的使用 函数指针 函数指针的定义 函数指针的使用 函数指针数组 函数指针数组的定义 函
  • Opencv-Python学习(五)

    一 傅里叶变换 傅里叶变换的详细过程及推导可以看一个大佬写的 我这里就不介绍了 链接 傅里叶分析之掐死教程 完整版 更新于2014 06 06 知乎 我这里就介绍一下傅里叶变换的一些概念和opencv中如何实现傅里叶变换 低频 变化缓慢的灰
  • Microsoft Skype产品线梳理

    目录 前言 1 Skype应用程序 2 Skype for Business 3 Skype电话 4 Skype号码 5 Skype连接 总结
  • FPGA:三种基本门电路设计(与门、或门、非门)

    FPGA的设计跟数电是紧密相连的 而我们学习数电时候 学习的第一个内容就是数字逻辑基础 这里面就包含了我们今天要讲解的三种基本的门电路 这里 我们依次讲解过来 1 与门 定义 有两个或多个输入 但只有一个输出 只有在所有输入都是高但电平时才
  • 决策树学习笔记整理

    本文目的 最近一段时间在Coursera上学习Data Analysis 里面有个assignment涉及到了决策树 所以参考了一些决策树方面的资料 现在将学习过程的笔记整理记录于此 作为备忘 算法原理 决策树 Decision Tree
  • GCD(容斥定理)

    Time Limit 6000 3000ms Java Other Memory Limit 32768 32768K Java Other Problem Description Given 5 integers a b c d k yo
  • Python爬虫面试知识

    爬虫知识 网络爬虫又称网页蜘蛛 爬虫即是网络上爬行的蜘蛛 可以将理解为一种在互联网上自动提取网页信息并进行解析数据的程序 网络爬虫主要的分类有 聚焦网络爬虫 增量网络爬虫 通用网络爬虫 深层网络爬虫 Robots协议又称机器人协议 通常在网
  • 单片机学习笔记1--资料下载、环境搭建(基于百问网STM32F103系列教程)

    第1篇 资料下载 环境搭建 第一章 百问网视频体系及学习路线 1 1课程视频变化 2011 2020 百问网录制了10年的Linux视频 2021 1 首次进入单片机领域 发布单片机课程 2 重新录制Linux课程 新芯片 新内核 新路线
  • 【Vue.js学习】三、Vue案例:计数器

    Vue js学习 三 Vue案例 计数器 一 HTML页面 二 Js代码 三 效果 实现计数器 要用到Vue的监听语法 v on click 函数名 声明函数后 在js中写入 methods 进行对函数的控制 下面进行详细解释 一 HTML
  • 成功转行Python工程师,年薪35W+,吐血整理

    这是给转行做Python的小白的参考 无论是从零开始 或者是转行的朋友来说 这都是值得一看的 也是可以作为一种借鉴吧 而且我决定转行IT 互联网 行业 其实理由也很简单 不用动体力 大多数动的是脑力工作 而且现在的互联网趋势很明显 再者看到
  • THINKPHP5.1在windows系统下,安装GateWayWorker

    一 GateWayWorker简单介绍 a GatewayWorker基于Workerman开发的一个项目框架 用于快速开发TCP长连接应用 例如app推送服务端 即时IM服务端 游戏服务端 物联网 智能家居等等 b 如果你的项目是长连接并