think-swoole,tp6的websocket实现

TP6的websocket实现

基于tp6,简单实现WebSocket,这一篇就够了。
学习路线

php
tp6(事件机制)
swoole的websocket实现
think-swoole在tp6中实现websocket
nginx代理
think-swoole (案例文档)

下面的代码,是假设在你对TP6的事件机制和swoole的websocket原生实现有所了解的基础上进行的。

websocket
websocket是出于osi模型应用层的长连接协议,允许全双工通信。更多websocket知识点— 点击这里
websocket提供了一整套用API,查看详细文档— 点击这里
swoole
swoole是PHP一套特别框架,是一个面向生产环境的 PHP 异步网络通信引擎,使 PHP 开发人员可以编写高性能的异步并发 TCP、UDP、Unix Socket、HTTP,WebSocket 服务。详细文档— 点击这里
Nginx
nginx代理基本知识点。nginx反向代理如何实现。

代码实现
在应用根目录下创建事件订阅类

php think make:subscribe WebSocket

WebSocket.php

<?php
declare (strict_types = 1);

namespace app\subscribe;

use app\Request;
use Swoole\Server;
use Swoole\WebSocket\Frame;
use think\cache\driver\Redis;
use think\Container;

class WebSocket
{
    protected $websocket = null;
    protected $server = null;
    
    public function __construct(Server $server, \think\swoole\Websocket $websocket, Container $container)
    {
        $this->websocket = $websocket;//依赖注入的方式
        $this->server = $server;
    }
   
    public function onConnect(Request $request){}
    
    // 监听客户连接
    public function onOpen(Request $request)
    {
        $fd = $this->websocket->getSender();// 获取连接标识
        $this->server->push($fd , 'something');// 发送给客户端
    }
    
    // 监听客户端发送消息
    public function onMessage(Server $server,Frame $frame)
    {
        $fd = $frame->fd; // 为当前连接唯一值
        $msg = json_decode($frame->data , true) ;// 获取cli上传的消息,json格式
        $this->server->push($fd , $msg);// 发送给客户端
    }
    
    //onClose触发的事件
    public function onClose()
    {
        // 一般做一些资源释放的动作
    }
}

修改app/config/swoole.php配置文件,没有的话就去vender扩展里面找think-swoole的扩展文件复制出来

<?php

use think\swoole\websocket\socketio\Handler;

return [
    'server'     => [
        'host'      => env('SWOOLE_HOST', '127.0.0.1'), // 监听地址
        'port'      => env('SWOOLE_PORT', 9000), // 监听端口
        'mode'      => SWOOLE_PROCESS, // 运行模式 默认为SWOOLE_PROCESS
        'sock_type' => SWOOLE_SOCK_TCP, // sock type 默认为SWOOLE_SOCK_TCP
        'options'   => [
            'pid_file'              => runtime_path() . 'swoole.pid',
            'log_file'              => runtime_path() . 'swoole.log',
            'daemonize'             => false,
            // Normally this value should be 1~4 times larger according to your cpu cores.
            'reactor_num'           => swoole_cpu_num(),
            'worker_num'            => swoole_cpu_num(),
            'task_worker_num'       => swoole_cpu_num(),
            'enable_static_handler' => true,
            'document_root'         => root_path('public'),
            'package_max_length'    => 20 * 1024 * 1024,
            'buffer_output_size'    => 10 * 1024 * 1024,
            'socket_buffer_size'    => 128 * 1024 * 1024,
        ],
    ],
    'websocket'  => [
        'enable'        => true,// 启动websocket

        'ping_interval' => 25000,
        'ping_timeout'  => 60000,
        'room'          => [
            'type'  => 'table',
            'table' => [
                'room_rows'   => 4096,
                'room_size'   => 2048,
                'client_rows' => 8192,
                'client_size' => 2048,
            ],
            'redis' => [
                'host'          => '127.0.0.1',
                'port'          => 6379,
                'max_active'    => 3,
                'max_wait_time' => 5,
            ],
        ],
        'listen'        => [],
        'subscribe'     => [
            app\subscribe\WebSocketEvent::class
            ],
    ],
    'rpc'        => [
        'server' => [
            'enable'   => false,
            'port'     => 9000,
            'services' => [
            ],
        ],
        'client' => [
        ],
    ],
    'hot_update' => [
        'enable'  => env('APP_DEBUG', false),
        'name'    => ['*.php'],
        'include' => [app_path()],
        'exclude' => [],
    ],
    //连接池
    'pool'       => [
        'db'    => [
            'enable'        => true,
            'max_active'    => 3,
            'max_wait_time' => 5,
        ],
        'cache' => [
            'enable'        => true,
            'max_active'    => 3,
            'max_wait_time' => 5,
        ],
        //自定义连接池
    ],
    'coroutine'  => [
        'enable' => true,
        'flags'  => SWOOLE_HOOK_ALL,
    ],
    'tables'     => [],
    //每个worker里需要预加载以共用的实例
    'concretes'  => [],
    //重置器
    'resetters'  => [],
    //每次请求前需要清空的实例
    'instances'  => [],
    //每次请求前需要重新执行的服务
    'services'   => [],
];

在根目录下执行

php think swoole启动监听

如果启动失败,根据提示信息修改
如果前端连接失败,一般是被nginx或防火墙拦截了。
前端html测试文件

<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, user-scalable=no">
  <title>websocket</title>
 </head>
 <body>
 <input id="text" value="">
 <input type="submit" value="send" onclick="start()">
 <input type="submit" value="close" onclick="close()">
<div id="msg"></div>
 <script>
    /**
      *0:未连接
      *1:连接成功,可通讯
      *2:正在关闭
      *3:连接已关闭或无法打开
      */
    //创建一个webSocket 实例
	var webSocket  = new  WebSocket("ws://127.0.0.1:9000");


    webSocket.onerror = function (event){
        onError(event);
    };

    // 打开websocket
    webSocket.onopen = function (event){
        onOpen(event);
    };

    //监听消息
    webSocket.onmessage = function (event){
        onMessage(event);
    };


    webSocket.onclose = function (event){
        onClose(event);
    }

    //关闭监听websocket
    function onError(event){
        document.getElementById("msg").innerHTML = "<p>close</p>";
        console.log("error"+event.data);
    };

    function onOpen(event){
        console.log("open:"+sockState());
        document.getElementById("msg").innerHTML = "<p>Connect to Service</p>";
    };

    function onMessage(event){
        console.log("onMessage");
        document.getElementById("msg").innerHTML += "<p>response:"+event.data+"</p>"
    };

    function onClose(event){
        document.getElementById("msg").innerHTML = "<p>close</p>";
        console.log("close:"+sockState());
        webSocket.close();
    }

    function sockState(){
        var status = ['未连接','连接成功,可通讯','正在关闭','连接已关闭或无法打开'];
            return status[webSocket.readyState];
    }

    function start(event){
        console.log(webSocket);
        var msg = document.getElementById('text').value;
        document.getElementById('text').value = '';
        console.log("send:"+sockState());
        console.log("msg="+msg);
        webSocket.send("msg="+msg);
        document.getElementById("msg").innerHTML += "<p>request"+msg+"</p>"
    };

    function close(event){
        webSocket.close();
    }
 </script>
 </body>
</html>
服务端
Text-to-HTML conversion tool
前端
在这里插入图片描述
  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值