Примеры использования

Практические примеры использования Localzet Cluster для различных сценариев.

Простой чат

Структура файлов

project/
├── register.php
├── gateway.php
├── business.php
├── Events.php
└── start.php

register.php

<?php
use localzet\Cluster\Register;

require_once __DIR__ . '/vendor/autoload.php';

$register = new Register('text://0.0.0.0:1236');
$register->name = 'Register';
$register->secretKey = 'chat-secret-key';

if (!defined('GLOBAL_START')) {
    \localzet\Server::runAll();
}

gateway.php

<?php
use localzet\Server;
use localzet\Cluster\Gateway;

require_once __DIR__ . '/vendor/autoload.php';

$gateway = new Gateway("Websocket://0.0.0.0:7273");
$gateway->name = 'ChatGateway';
$gateway->count = 4;
$gateway->lanIp = '127.0.0.1';
$gateway->startPort = 2800;
$gateway->pingInterval = 55;
$gateway->pingData = '{"type":"ping"}';
$gateway->registerAddress = '127.0.0.1:1236';
$gateway->secretKey = 'chat-secret-key';

if (!defined('GLOBAL_START')) {
    Server::runAll();
}

Events.php

<?php
use localzet\Server;
use localzet\Cluster\Lib\Gateway;

class Events
{
    public static function onConnect($client_id)
    {
        Server::log("Client connected: $client_id");
        Gateway::sendToClient($client_id, json_encode([
            'type' => 'system',
            'message' => 'Welcome to chat!'
        ]));
    }

    public static function onMessage($client_id, $message)
    {
        $data = json_decode($message, true);
        
        if (!$data || !isset($data['type'])) {
            return;
        }
        
        switch ($data['type']) {
            case 'join_room':
                // Добавить в комнату
                $room = $data['room'] ?? 'general';
                Gateway::joinGroup($client_id, $room);
                
                Gateway::sendToClient($client_id, json_encode([
                    'type' => 'system',
                    'message' => "Joined room: $room"
                ]));
                
                // Уведомить других в комнате
                Gateway::sendToGroup($room, json_encode([
                    'type' => 'user_joined',
                    'client_id' => $client_id
                ]), [$client_id]);
                break;
                
            case 'leave_room':
                $room = $data['room'] ?? 'general';
                Gateway::leaveGroup($client_id, $room);
                break;
                
            case 'message':
                // Отправить сообщение в комнату
                $room = $_SESSION['current_room'] ?? 'general';
                Gateway::sendToGroup($room, json_encode([
                    'type' => 'chat_message',
                    'client_id' => $client_id,
                    'message' => $data['message'],
                    'timestamp' => time()
                ]));
                break;
                
            case 'private':
                // Приватное сообщение
                if (isset($data['target_uid'])) {
                    Gateway::sendToUid($data['target_uid'], json_encode([
                        'type' => 'private_message',
                        'from_uid' => $_SESSION['uid'] ?? null,
                        'message' => $data['message']
                    ]));
                }
                break;
        }
    }

    public static function onClose($client_id)
    {
        Server::log("Client disconnected: $client_id");
        
        // Уведомить о выходе из всех групп
        $session = Gateway::getSession($client_id);
        if ($session && isset($session['rooms'])) {
            foreach ($session['rooms'] as $room) {
                Gateway::sendToGroup($room, json_encode([
                    'type' => 'user_left',
                    'client_id' => $client_id
                ]));
            }
        }
    }
}

business.php

<?php
use localzet\Server;
use localzet\Cluster\Business;

require_once __DIR__ . '/vendor/autoload.php';
require_once __DIR__ . '/Events.php';

$worker = new Business();
$worker->name = 'ChatBusinessWorker';
$worker->count = 4;
$worker->registerAddress = '127.0.0.1:1236';
$worker->secretKey = 'chat-secret-key';
$worker->eventHandler = 'Events';

if (!defined('GLOBAL_START')) {
    Server::runAll();
}

start.php

<?php
define('GLOBAL_START', 1);

require_once __DIR__ . '/register.php';
require_once __DIR__ . '/gateway.php';
require_once __DIR__ . '/business.php';

Запуск

php start.php start

Чат с аутентификацией

class Events
{
    public static function onConnect($client_id)
    {
        // Ожидаем токен аутентификации
    }

    public static function onMessage($client_id, $message)
    {
        $data = json_decode($message, true);
        
        if (!isset($_SESSION['authenticated'])) {
            // Обработка аутентификации
            if ($data['type'] === 'auth' && isset($data['token'])) {
                $user = validateToken($data['token']); // Ваша функция
                
                if ($user) {
                    $_SESSION['authenticated'] = true;
                    $_SESSION['uid'] = $user['id'];
                    $_SESSION['username'] = $user['username'];
                    
                    // Привязать к UID
                    Gateway::bindUid($client_id, $user['id']);
                    
                    Gateway::sendToClient($client_id, json_encode([
                        'type' => 'auth_success',
                        'user' => $user
                    ]));
                } else {
                    Gateway::sendToClient($client_id, json_encode([
                        'type' => 'auth_error',
                        'message' => 'Invalid token'
                    ]));
                    Gateway::closeClient($client_id);
                }
            }
            return;
        }
        
        // Обработка сообщений для аутентифицированных пользователей
        switch ($data['type']) {
            case 'message':
                $room = $data['room'] ?? 'general';
                Gateway::sendToGroup($room, json_encode([
                    'type' => 'chat_message',
                    'uid' => $_SESSION['uid'],
                    'username' => $_SESSION['username'],
                    'message' => $data['message'],
                    'timestamp' => time()
                ]));
                break;
        }
    }

    public static function onClose($client_id)
    {
        // Очистка данных пользователя при отключении
    }
}

function validateToken($token)
{
    // Ваша логика проверки токена
    // Например, проверка JWT или запрос в БД
    return ['id' => 123, 'username' => 'john'];
}

Система уведомлений

class Events
{
    public static function onMessage($client_id, $message)
    {
        $data = json_decode($message, true);
        
        if ($data['type'] === 'subscribe') {
            // Подписка на уведомления по типу
            $notificationType = $data['notification_type'];
            Gateway::joinGroup($client_id, "notifications_$notificationType");
            
            Gateway::sendToClient($client_id, json_encode([
                'type' => 'subscribed',
                'notification_type' => $notificationType
            ]));
        }
    }
}

// Внешнее приложение отправляет уведомления
use localzet\Cluster\Client;

Client::$registerAddress = '127.0.0.1:1236';
Client::$secretKey = 'chat-secret-key';

// Уведомление всем подписчикам
Client::sendToGroup('notifications_system', json_encode([
    'type' => 'notification',
    'title' => 'System Update',
    'message' => 'Server will restart in 5 minutes'
]));

// Уведомление конкретному пользователю
$uid = 12345;
Client::sendToUid($uid, json_encode([
    'type' => 'notification',
    'title' => 'New Message',
    'message' => 'You have a new message'
]));

Игровой сервер

class Events
{
    public static function onConnect($client_id)
    {
        // Инициализация игровой сессии
        $_SESSION['game_state'] = 'lobby';
        $_SESSION['score'] = 0;
    }

    public static function onMessage($client_id, $message)
    {
        $data = json_decode($message, true);
        
        switch ($data['action']) {
            case 'join_game':
                $gameId = $data['game_id'];
                Gateway::joinGroup($client_id, "game_$gameId");
                
                $_SESSION['game_state'] = 'playing';
                $_SESSION['game_id'] = $gameId;
                
                // Уведомить других игроков
                Gateway::sendToGroup("game_$gameId", json_encode([
                    'type' => 'player_joined',
                    'client_id' => $client_id
                ]), [$client_id]);
                break;
                
            case 'game_action':
                // Распространение игрового действия
                $gameId = $_SESSION['game_id'];
                Gateway::sendToGroup("game_$gameId", json_encode([
                    'type' => 'game_action',
                    'client_id' => $client_id,
                    'action' => $data['action_data']
                ]));
                break;
                
            case 'update_score':
                $_SESSION['score'] = $data['score'];
                
                // Отправить топ игроков
                $topPlayers = getTopPlayers($_SESSION['game_id']);
                Gateway::sendToClient($client_id, json_encode([
                    'type' => 'leaderboard',
                    'players' => $topPlayers
                ]));
                break;
        }
    }
    
    public static function onClose($client_id)
    {
        // Удалить из игры
        if (isset($_SESSION['game_id'])) {
            Gateway::leaveGroup($client_id, "game_{$_SESSION['game_id']}");
            
            Gateway::sendToGroup("game_{$_SESSION['game_id']}", json_encode([
                'type' => 'player_left',
                'client_id' => $client_id
            ]));
        }
    }
}

Клиентский код (JavaScript)

const ws = new WebSocket('ws://localhost:7273');

ws.onopen = function() {
    console.log('Connected');
    
    // Аутентификация
    ws.send(JSON.stringify({
        type: 'auth',
        token: 'user-token-here'
    }));
};

ws.onmessage = function(event) {
    const data = JSON.parse(event.data);
    
    switch(data.type) {
        case 'auth_success':
            console.log('Authenticated:', data.user);
            break;
            
        case 'chat_message':
            displayMessage(data);
            break;
            
        case 'notification':
            showNotification(data.title, data.message);
            break;
    }
};

// Отправка сообщения
function sendMessage(room, message) {
    ws.send(JSON.stringify({
        type: 'message',
        room: room,
        message: message
    }));
}

// Присоединиться к комнате
function joinRoom(room) {
    ws.send(JSON.stringify({
        type: 'join_room',
        room: room
    }));
}