ThinkPHP5与GatewayWorker集成(windows环境)

  1. 安装GatewayWorker类库
composer require workerman/gateway-worker-for-win
composer require workerman/workerman-for-win

在这里插入图片描述在这里插入图片描述
2.安装完成后 在vendor文件夹里
在这里插入图片描述3.代码
在application目录下,创建一个应用模块,模块名称为gatewayapp,其目录结构如下
在这里插入图片描述
controller/GwEvents.php文件,该文件是业务逻辑处理类,实际开发中,只需要关注这个文件即可

<?php
namespace app\gatewayapp\controller;

use GatewayWorker\Lib\Gateway;

/**
 * 主逻辑
 * 主要是处理 onConnect onMessage onClose 三个方法
 * onConnect 和 onClose 如果不需要可以不用实现并删除
 */
class GwEvents {

    /**
     * 当客户端连接时触发
     * 如果业务不需此回调可以删除onConnect     *
     * @param int $client_id 连接id
     */
    public static function onConnect($client_id) {
        //当客户端连接时,向当前的client_id发送当前的连接id
            //控制台会报错 发json
        Gateway::sendToClient($client_id, json_encode(['message_type'=>'init','client_id'=>$client_id]));

        // 向所有人发送
       //Gateway::sendToAll(sprintf('用户 %s 已登录!',$client_id));
    }

    /**
     * 当客户端发来消息时触发
     * @param int $client_id 连接id
     * @param mixed $message 具体消息
     */
    public static function onMessage($client_id, $message) {

        //Gateway::sendToClient($client_id, sprintf('hi %s',$client_id));
        $message = json_decode($message, true);
        $message_type = $message['type'];
        switch($message_type)
        {
            //客户端发来的消息类型是login,
            case 'login':
                // uid
                $uid = $message['formid'];
                // 设置session
                $_SESSION = [
                    'id'       => $uid,
                ];

                // 将当前链接id与uid绑定
                 Gateway::bindUid($client_id, $uid);



                return;
                break;
            //客户端发送过来聊天消息,由服务器发送给他想发送的那个人,也就是toid
            case 'chatMessage':
                $content = $message['data']['mine']['data'];
                $formid = $message['data']['mine']['formid'];
                $to_id = $message['data']['to']['toid'];
                // $uid = $_SESSION['id'];
                $chat_message = [
                    'message_type' => 'chatMessage',//发送类型
                    'content'=>htmlspecialchars($content),//发送内容
                    'formid'=>$formid,//发送者的id
                    'toid'=>$to_id//接收者的id
                ];
                //发送给toid
                return Gateway::sendToUid($to_id, json_encode($chat_message));
                break;
//            case 'hide':
//            case 'online':
//                $status_message = [
//                    'message_type' => $message_type,
//                    'id'           => $_SESSION['id'],
//                ];
//                $_SESSION['online'] = $message_type;
//                Gateway::sendToAll(json_encode($status_message));
//                return;
//                break;
            case 'ping':
                return;
            default:
                echo "unknown message $message" . PHP_EOL;
        }
    }

    /**
     * 当用户断开连接时触发
     * @param int $client_id 连接id
     */
    public static function onClose($client_id) {
        // 向所有人发送
        GateWay::sendToAll(sprintf('用户 %s 已退出!',$client_id));
    }

}

controller/Index.php文件

<?php
namespace app\gatewayapp\controller;

use think\Controller;

class Index extends Controller {

    public function index() {
        $formid = input('formid');
        $toid = input('toid');
        $this->assign('formid',$formid);
        $this->assign('toid',$toid);
        return $this->fetch();
    }
}

view/index/index.html视图文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WebSocket示例</title>
     <script src="/static/jquery/jquery-3.1.1.min.js"></script>
</head>
<body>
<div>
    <input type="text" name="msg" id="aaa">
    <input id="sendMsg" type="button" value="发送">

</div>
<script type="text/javascript">

    var formid = {$formid};

    var toid = {$toid};
    var webSocket = null;

    initSocket();

    function initSocket() {
        if (!"WebSocket" in window) {
            console.log("您的浏览器不支持 WebSocket!");
            return;
        }
        webSocket = new WebSocket("ws://"+document.domain+":8283");
        webSocket.onopen = handleSend;
        webSocket.onmessage = handleMessage;
        webSocket.onclose = handleClose;
        webSocket.onerror = handleError;
    }

    // 向服务器端发送数据
    function handleSend() {
    }

    // 处理服务器端发送过来的数据
    function handleMessage(evt) {
        console.log(evt.data);
        //把json数据转成js对象
        var received_msg = eval("("+evt.data+")");
      // console.log(received_msg);
        switch(received_msg['message_type'])
        {
            //服务端ping客户端
            case 'ping':
                webSocket.send('{"type":"ping"}');
            // 接收的消息类型如果是init,再将页面上的formid发给服务器
            case 'init':
              //console.log(received_msg['id']+"登录成功");
                var bild  = '{"type":"login","formid":"'+formid+'"}';
                webSocket.send(bild);
                break;
            // 检测聊天数据
            case'chatMessage':
                console.log(received_msg['content']);
                break;
            // 离线消息推送
            case 'logMessage':
                setTimeout(function(){}, 1000);
                break;
            // 用户退出 更新用户列表
            case 'logout':
                break;
        }

    }
    // 处理连接关闭事件
    function handleClose() {
        console.log("连接已关闭...");
    }

    // 处理WebSocket错误
    function handleError() {
        console.log("WebSocketError!");
    }


    //取到input里的聊天数据,发送给服务器
    $('#sendMsg').on('click',function() {
        var content = $('input[name=msg]').val();
        var res = new Array();
        res['mine'] = {
            data: content,
            formid:formid,

        };
        res['to'] = {
            toid:toid
        };
        var mine = JSON.stringify(res.mine);
        var to = JSON.stringify(res.to);
        var chat_data = '{"type":"chatMessage","data":{"mine":' + mine + ', "to":' + to + '}}';
        console.log(chat_data);
        webSocket.send(chat_data);
    })

</script>
</body>
</html>

run/start_register.php文件

use GatewayWorker\Register;
use Workerman\Worker;
 
$registerInstance = new GwRegister();
call_user_func_array(array($registerInstance,'index'),array());
 
class GwRegister {
 
    public function __construct() {
        require_once dirname(__FILE__) . '/../../../vendor/autoload.php';
        include_once dirname(__FILE__).'/../const.php';
    }
 
    public function index() {
        // register 必须是text协议
        $registerAddress = sprintf('text://%s',GW_REGISTER_PROTOCOL);
        $register = new Register($registerAddress);
 
        // 如果不是在根目录启动,则运行runAll方法
        if(!defined('GLOBAL_START')) {
            Worker::runAll();
        }
    }
 
}

run/start_gateway.php文件

use Workerman\Worker;
use GatewayWorker\Gateway;
use Workerman\Autoloader;
 
$gatewayInstance = new GwGateway();
call_user_func_array(array($gatewayInstance,'index'),array());
 
class GwGateway {
 
    private $gatewayAddress;
 
    public function __construct() {
        require_once dirname(__FILE__) . '/../../../vendor/autoload.php';
        include_once dirname(__FILE__).'/../const.php';
        // gateway 进程,这里使用websocket协议
        $this->gatewayAddress = sprintf('websocket://%s',GW_GATEWAY_ADDRESS);
    }
 
    public function index() {
        $gateway = new Gateway($this->gatewayAddress);
        // 设置名称,方便status时查看
        $gateway->name = GW_GATEWAY_NAME;
        // 设置进程数,gateway进程数建议与cpu核数相同
        $gateway->count = GW_GATEWAY_COUNT;
        // 本机ip,分布式部署时请设置成内网ip(非127.0.0.1)
        $gateway->lanIp = GW_LOCAL_HOST_IP;
        // 内部通讯起始端口,假如$gateway->count=4,起始端口为4000
        // 则一般会使用4000 4001 4002 4003 4个端口作为内部通讯端口
        $gateway->startPort = GW_GATEWAY_START_PORT;
        // 服务注册地址
        $gateway->registerAddress = GW_REGISTER_ADDRESS;
 
        // 心跳间隔,单位:秒,0 表示不发送心跳检测
        $gateway->pingInterval = GW_GATEWAY_PING_INTERVAL;
        // 心跳数据
        $gateway->pingData = '{"type":"ping"}';
 
        /*
        // 当客户端连接上来时,设置连接的onWebSocketConnect,即在websocket握手时的回调
        $gateway->onConnect = function($connection) {
            $connection->onWebSocketConnect = function($connection , $http_header) {
                // 可以在这里判断连接来源是否合法,不合法就关掉连接
                // $_SERVER['HTTP_ORIGIN']标识来自哪个站点的页面发起的websocket链接
                if($_SERVER['HTTP_ORIGIN'] != 'http://kedou.workerman.net') {
                    $connection->close();
                }
                // onWebSocketConnect 里面$_GET $_SERVER是可用的
                // var_dump($_GET, $_SERVER);
            };
        };
        */
 
        // 如果不是在根目录启动,则运行runAll方法
        if(!defined('GLOBAL_START')) {
            Worker::runAll();
        }
    }
 
}

run/start_businessworker.php文件

use Workerman\Worker;
use GatewayWorker\BusinessWorker;
use Workerman\Autoloader;
 
$businessInstance = new GwBusinessWorker();
call_user_func_array(array($businessInstance,'index'),array());
 
class GwBusinessWorker {
 
    public function __construct() {
        require_once dirname(__FILE__) . '/../../../vendor/autoload.php';
        include_once dirname(__FILE__).'/../const.php';
    }
 
    public function index() {
        // bussinessWorker 进程
        $worker = new BusinessWorker();
        // worker名称
        $worker->name = GW_WORKER_NAME;
        // bussinessWorker进程数量
        $worker->count = GW_BUSINESS_WORKER_COUNT;
        // 服务注册地址
        $worker->registerAddress = GW_REGISTER_ADDRESS;
        //设置处理业务的类,此处制定Events的命名空间
        $worker->eventHandler = GW_BUSINESS_EVENT_HANDLER;
 
        // 如果不是在根目录启动,则运行runAll方法
        if(!defined('GLOBAL_START')) {
            Worker::runAll();
        }
    }
 
}

const.php常量定义文件,根据需要,修改相关常量对应的值。

// 注册协议
define('GW_REGISTER_PROTOCOL','0.0.0.0:1236');
 
// 注册地址
define('GW_REGISTER_ADDRESS','127.0.0.1:1236');
 
// 网关地址
define('GW_GATEWAY_ADDRESS','0.0.0.0:8283');
 
// 网关起始端口
define('GW_GATEWAY_START_PORT','2900');
 
// 心跳检测间隔,单位:秒,0 表示不发送心跳检测
define('GW_GATEWAY_PING_INTERVAL',10);
 
// 本机ip,分布式部署时请设置成内网ip(非127.0.0.1)
define('GW_LOCAL_HOST_IP','127.0.0.1');
 
// 网关名称
define('GW_GATEWAY_NAME','Gateway001');
 
// worker进程名称
define('GW_WORKER_NAME','BusinessWorker001');
 
// Gateway进程数量,建议与CPU核数相同
define('GW_GATEWAY_COUNT',2);
 
// BusinessWorker进程数量,建议设置为CPU核数的1倍-3倍
define('GW_BUSINESS_WORKER_COUNT',6);
 
// Business业务处理类,可以带命名空间
define('GW_BUSINESS_EVENT_HANDLER','app\gatewayapp\controller\GwEvents');

start_for_win.bat启动文件

php run\start_register.php run\start_gateway.php run\start_businessworker.php
pause

双击start_for_win.bat文件,启动websocket服务,启动成功后的界面如下:
在这里插入图片描述
打开浏览器,定位到视图url,可以多开几个浏览器,然后切换到任何一个浏览器的控制台,效果如下
在这里插入图片描述
在这里插入图片描述在这里插入图片描述

撒花,完结
转载https://blog.csdn.net/tdcqfyl/article/details/81170420#commentBox

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值