hyperf websocket服务

安装hyperf/websocket-server组件

composer require hyperf/websocket-server

websocket服务配置 config/autoload/server.php

<?php

declare(strict_types=1);

use Hyperf\Server\Event;
use Hyperf\Server\Server;
use Swoole\Constant;

return [
    'mode' => SWOOLE_PROCESS,
    'servers' => [
        [
            'name' => 'http',
            'type' => Server::SERVER_HTTP,
            'host' => '0.0.0.0',
            'port' => 9501,
            'sock_type' => SWOOLE_SOCK_TCP,
            'callbacks' => [
                Event::ON_REQUEST => [Hyperf\HttpServer\Server::class, 'onRequest'],
            ],
        ],
        //websocket服务配置
        [
            'name' => 'ws',
            'type' => Server::SERVER_WEBSOCKET,
            'host' => '0.0.0.0',
            'port' => 9504,
            'sock_type' => SWOOLE_SOCK_TCP,
            'callbacks' => [
                Event::ON_HAND_SHAKE => [Hyperf\WebSocketServer\Server::class, 'onHandShake'],
                Event::ON_MESSAGE => [Hyperf\WebSocketServer\Server::class, 'onMessage'],
                Event::ON_CLOSE => [Hyperf\WebSocketServer\Server::class, 'onClose'],
            ],
        ],
    ],
    'settings' => [
        Constant::OPTION_ENABLE_COROUTINE => true,
        Constant::OPTION_WORKER_NUM => swoole_cpu_num(),
        Constant::OPTION_PID_FILE => BASE_PATH . '/runtime/hyperf.pid',
        Constant::OPTION_OPEN_TCP_NODELAY => true,
        Constant::OPTION_MAX_COROUTINE => 100000,
        Constant::OPTION_OPEN_HTTP2_PROTOCOL => true,
        Constant::OPTION_MAX_REQUEST => 100000,
        Constant::OPTION_SOCKET_BUFFER_SIZE => 2 * 1024 * 1024,
        Constant::OPTION_BUFFER_OUTPUT_SIZE => 2 * 1024 * 1024,
        // Task Worker 数量,根据您的服务器配置而配置适当的数量
        'task_worker_num' => 2,
        // 因为 `Task` 主要处理无法协程化的方法,所以这里推荐设为 `false`,避免协程下出现数据混淆的情况
        'task_enable_coroutine' => false,
    ],
    'callbacks' => [
        Event::ON_WORKER_START => [Hyperf\Framework\Bootstrap\WorkerStartCallback::class, 'onWorkerStart'],
        Event::ON_PIPE_MESSAGE => [Hyperf\Framework\Bootstrap\PipeMessageCallback::class, 'onPipeMessage'],
        Event::ON_WORKER_EXIT => [Hyperf\Framework\Bootstrap\WorkerExitCallback::class, 'onWorkerExit'],
        // Task callbacks
        Event::ON_TASK => [Hyperf\Framework\Bootstrap\TaskCallback::class, 'onTask'],
        Event::ON_FINISH => [Hyperf\Framework\Bootstrap\FinishCallback::class, 'onFinish'],
    ],
];

创建websocket服务控制器 app/Controller/WebSocketController.php

<?php
declare(strict_types=1);

namespace App\Controller;

use Hyperf\Contract\OnCloseInterface;
use Hyperf\Contract\OnMessageInterface;
use Hyperf\Contract\OnOpenInterface;
use Swoole\Http\Request;
use Swoole\Server;
use Swoole\Websocket\Frame;
use Swoole\WebSocket\Server as WebSocketServer;

class WebSocketController implements OnMessageInterface, OnOpenInterface, OnCloseInterface
{
    public function onMessage($server, Frame $frame): void
    {
            echo "message\n";
        $server->push($frame->fd, 'Recv: ' . $frame->data);
    }

    public function onClose($server, int $fd, int $reactorId): void
    {
        var_dump('closed');
    }

    public function onOpen($server, Request $request): void
    {
            echo "open\n";
        $server->push($request->fd, 'Opened');
    }
}

配置websocket路由 config/route.php

<?php

declare(strict_types=1);

use Hyperf\HttpServer\Router\Router;
use App\Middleware\Middleware1;
use App\Middleware\Middleware2;

Router::addServer('ws', function () {
    Router::get('/', 'App\Controller\WebSocketController');
});

Router::addRoute(['GET', 'POST', 'HEAD'], '/', 'App\Controller\IndexController@index');

Router::get('/favicon.ico', function () {
    return '';
});

启动hyperf服务

php bin/hyperf.php start

websocket客户端测试文件(websocket.html)

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebSocket测试</title>
    <script>
        function initWebSocket(wsUri) {
            var websocket = new WebSocket(wsUri);
            websocket.onopen = function(evt) {
                console.log('连接建立中... '+wsUri);
            };
            websocket.onclose = function(evt) {
                console.log('连接关闭中...', evt);
            };
            websocket.onmessage = function(evt) {
                console.log('收到来自服务端的消息:', evt.data);
            };
            websocket.onerror = function(evt) {
                console.log('发生错误...', evt);
            };
            return websocket;
        }

        var websocket = initWebSocket("ws://118.195.173.53:9504");
        var msg, i = 0;
        var loop = setInterval(function(){
            msg = "Hello " + (i++);
            if(websocket.readyState == WebSocket.OPEN) {
                websocket.send(msg);
                console.log('已发送消息:' + msg);
            } else {
                clearInterval(loop);
                console.log('连接已关闭,拜拜~');
            }
        }, 3000);
    </script>
</head>
<body>
    请按 F12 打开控制台查看消息
</body>
</html>

浏览器 console打印

连接建立中... ws://118.195.173.53:9504
websocket.html:17 收到来自服务端的消息: Opened
websocket.html:31 已发送消息:Hello 0
websocket.html:17 收到来自服务端的消息: Recv: Hello 0
websocket.html:31 已发送消息:Hello 1
websocket.html:17 收到来自服务端的消息: Recv: Hello 1
websocket.html:31 已发送消息:Hello 2
websocket.html:17 收到来自服务端的消息: Recv: Hello 2

浏览器 network > ws > messages 打印

Hello 1    7    
01:28:36.098
Recv: Hello 1    13    
01:28:36.145
Hello 2    7    
01:28:39.098
Recv: Hello 2    13    
01:28:39.295
Hello 3    7    
01:28:42.097
Recv: Hello 3
上一篇:Echarts入门和使用


下一篇:echarts.js - 动态数据 + 时间坐标轴