workerman 使用服务端和客户端

服务端安装

composer require workerman/workerman

客户端安装

composer require textalk/websocket

<?php

namespace App\Controllers;
use Workerman\Worker;
use Workerman\Lib\Timer;
use WebSocket\Client;
class Workerman extends BaseController
{
     protected $uidConnections = [];
    protected $HEARTBEAT_TIME = '60';
    public $code_arr = [
        '100' => ['code'=>100, 'msg'=>'连接成功'],
        '101' => ['code'=>101, 'msg'=>'登录成功'],
        '102' => ['code'=>102, 'msg'=>'发送数据'],
        '103' => ['code'=>103, 'msg'=>'接收成功'],
        '131' => ['code'=>131, 'msg'=>'发送失败'],
        ];
    protected $worker = null;
    public $count = 0;

    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'workerman:websocket';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * 
     * @var string
     */
    protected $redis = '';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    // public function __construct()
    // {
    //     parent::__construct();
    // }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $this->start();
    }

    public function start()
    {
          $this->worker = new Worker('websocket://0.0.0.0:1818');

          $this->onConnect();
          $this->onMessage();
          $this->onClose();
          $this->redis = $this->redisdb();
        

          Worker::runAll();
    }

    public function onConnect() {
        $this->worker->onConnect = function($connection) {
            $connection->send(json_encode($this->code_arr['100']));
            $this->count++;
            $msg = "新的连接 目前连接数 {$this->count}";
            var_dump($msg);
            log_message('error',$msg);

        };
    }

    public function onMessage() {
        $this->worker->onMessage = function ($connection, $data){
            $connection->lastMessageTime = time();  //更新上一次会话时间
            //客户端心跳 直接返回
            if ($data == "") {
                return;
            }
            $data = json_decode($data, true);
            if (empty($data['uid'])) {
                $connection->close();
                return;
            }
            $uid = $data['uid'];//这里的uid根据自己的情况去验证
            switch ($data['type']) {
                case 'login':
                    // 保存该用户的输送数据
                    $connection->uid = $uid;
                    $this->uidConnections[$uid] = $connection;
                    $msg = "uid:{$uid} 登录成功 目前登录数".count($this->uidConnections);
                    $r = $this->redis->get('ddd:'.$uid);
                    if($r){
                         $this->redis->delete('ddd:'.$uid);
                    }
                    log_message('error',$r.'---');
                    // var_dump($msg);
                    log_message('error',$msg);
                    $connection->send(json_encode(['sss'=>$r]));
                    break;
                case 'send':
                    // 发送消息
                    $res = $this->sendMessageByUid($uid, $data['info']);
                    $msg = "发送成功";
                    if (!$res) {
                        $msg = "发送失败";
                    }
                    // var_dump($msg);
                    log_message('error',$msg);
                    break;
                case 'message':
                    break;
            }
        };
    }

    // 针对uid推送数据
    public function sendMessageByUid($uid, $message)
    {
        if(isset($this->uidConnections[$uid]))
        {
            $send_data = $this->code_arr['102'];
            $send_data['info'] = $message;
            $this->uidConnections[$uid]->send(json_encode($send_data));
            return true;
        }
        return false;
    }

     public function onClose() {
        $this->worker->onClose = function ($connection){
            $this->count--;
            if(isset($connection->uid)) {
                $msg = "uid:{$connection->uid} 已断开";
                var_dump($msg);
            log_message('error',$msg);
                // Log::write("$msg", 'WorkerManServer');
                // 连接断开时删除映射 和 二维码图片
                unset($this->uidConnections[$connection->uid]);
                (new OtherService())->delLoginQrCode($connection->uid);
            }
            $msg = "连接已断开 目前连接数 {$this->count}";
            var_dump($msg);
            log_message('error',$msg);
        };
     }
     public function redisdb($db=0)
     {
         $redis=new \redis();
         $redis->connect("127.0.0.1","6379");
         $redis->select($db);
         return $redis;
     }
     public function test($value='')
     {
          $data = array(
               'uid' => 1,
               'type' => 'send',
               'info' => ['sss'=>11]
          );
          $json = json_encode($data);
          $client = new Client("ws://127.0.0.1:1818");
          $client->send($json);
          $message = $client->receive();
          log_message('error',$message);
          $client->close();
     }

}
?>

服务端执行

Workerman/handle;方法

客户端请求链接

Workerman/test

前端代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div style="margin: 0 auto;width: 800px">
    <h2>聊天室</h2>
    <textarea type="text" style="border: 1px solid black;width: 800px;height: 200px;" id="his"></textarea>
    <input type="text" style="width:740px" id="sendMsg">&nbsp;<button id="send">发送</button>
</div>
</body>
</html>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
 
    $(function () {
        var ws = new WebSocket("ws://127.0.0.1:1818");

       $('#send').click(function () {
           msg = $('#sendMsg').val();
           $('#sendMsg').val('');
           ws.send(msg);
       });
        ws.onopen = function() {
            $('#his').append("服务器连接成功.....");
            $('#his').append("\n");
        };
        ws.onmessage = function(e) {
            $('#his').append(e.data);
            $('#his').append("\n");
        };
 
    });
</script>

https的看这个:

workerman 使用服务端和客户端 SSL证书版-CSDN博客

### ThinkPHP 5.1 中集成 Workerman 及 Gateway 进行开发 #### 创建项目并安装依赖 为了在 ThinkPHP 5.1 中集成 WorkerMan Gateway,首先需要创建一个新的 ThinkPHP 项目: ```bash composer create-project topthink/think=5.1.x-dev tp5 [^1] ``` 进入项目目录 `tp5` 并通过 Composer 安装 WorkerMan GatewayWorker 扩展包。 ```bash cd tp5 composer require workerman/gateway-worker ``` #### 配置 WorkerMan 启动文件 在项目的根目录下创建一个名为 `start.php` 的启动脚本用于运行 WorkerMan 服务端程序。此文件内容如下所示: ```php <?php // start.php 文件路径位于项目根目录 use GatewayWorker\Lib\Gateway; require_once __DIR__ . '/vendor/autoload.php'; $worker = new \GatewayWorker\BusinessWorker(); $worker->count = 4; // 设置进程数 $worker->name = 'Chat'; // 名字 $worker->registerAddress = '127.0.0.1:1238'; $worker->eventHandler = '\App\WebSocketEventHandler'; // 自定义事件处理器类名空间位置 // 如果不是在根目录启动,则运行runAll方法 if (!defined('GLOBAL_START')) { Worker::runAll(); } ``` 注意这里指定了自定义的 WebSocket 事件处理类 `\App\WebSocketEventHandler` ,该类应该放置于应用命名空间下的适当位置以便加载器能够找到它。 #### 实现 WebSocket 逻辑 接下来,在应用程序内实现具体的业务逻辑。假设已经按照上述配置设置了 `$worker->eventHandler` 属性指向了一个特定的 PHP 类来负责接收来自客户端的消息以及向其发送消息等功能。那么可以在 `app/` 下新建相应的 PHP 文件比如命名为 `WebSocketEventHandler.php` 来编写实际功能代码: ```php <?php namespace App; class WebSocketEventHandler extends \GatewayWorker\GateWay { public static function onConnect($client_id) { echo "new connection from {$client_id}\n"; } /** * 当收到客户端发来的数据时触发 */ public static function onMessage($client_id, $message) { // 发送 hello world 给当前连接上的客户端 self::sendToClient($client_id,'hello world'); // 将 client_id uid 关联起来 \GatewayWorker\Lib\Gateway::bindUid($client_id, uniqid()); } protected static function sendToClient($client_id,$msg){ global $_GW_; $_GW_->gateway->sendToClient($client_id,json_encode(['type'=>'chat','content'=>$msg])); } /** * 当有客户端断开链接的时候触发 */ public static function onClose($client_id) { echo "connection closed\n"; } } ``` 这段代码实现了当新用户加入聊天室(`onConnect`)、接收到消息(`onMessage`)离开房间(`onClose`)三个主要场景下的行为响应函数,并且包含了简单的绑定 UID 到 Client ID 的操作[^3]。 #### 测试 Websocket 功能 完成以上设置之后就可以尝试重启 WorkerMan 服务器以使更改生效。对于 Windows 用户来说可以执行之前提到过的批处理命令 `start_for_win.bat` 来开启服务[^2];而对于 Linux 或 MacOSX 系统则可以直接利用命令行工具 php 去调用刚才建立好的入口文件 `php start.php start -d` (其中 `-d` 参数表示以后台守护模式运行)。 最后一步就是验证整个系统的正常运作情况了——可以通过浏览器或其他支持 WebSocket 协议的应用模拟作为客户端发起请求并与后端交互从而检验是否成功搭建起了基于 TP5 + WorkerMan/Gateway 构建而成的服务架构体系。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值