OpenSwoole: используйте UDP-сервер для отправки сообщений в канал

Вопрос или проблема

OpenSwoole: используйте UDP-сервер для отправки сообщений в канал

Я пытаюсь начать работать с OpenSwoole и использую встроенный UDP сервер. Я хотел бы отправить любые полученные сообщения в канал, чтобы другая корутина могла их обработать. Я много искал в Google и не нашел очевидного способа сделать это.

Вот код, который у меня сейчас есть:

// Создаем канал с местом для 1000 сообщений
$chan = new OpenSwoole\Coroutine\Channel(1000);

co::run(function () use ($chan) {

    // Слушатель
    go(function() use ($chan) {
        // Чтение из канала
        while (1) {
            $data_read = $chan->pop();
            echo ("Данные прочитаны: $data_read\n");
        }
    });
});

// UDP сервер

// Установите параметры корутины перед запуском сервера
OpenSwoole\Coroutine::set([
        'enable_coroutine' => true
]);

// Запустите новый UDP сервер на 12.0.0.1, слушая порт 9502
$server = new OpenSwoole\Server('127.0.0.1', 9502, OpenSwoole\Server::POOL_MODE, OpenSwoole\Constant::SOCK_UDP);

// Настройте обратный вызов события входящих данных, названный 'Packet'
$server->on('Packet', function ($server, $data, $clientInfo) use ($chan)
{
    echo ("Данные записаны: $data\n");
    $chan->push($data);
});

// Запустите сервер и начните принимать входящие запросы
$server->start();

Но когда я запускаю его, я получаю ошибку:

===================================================================
 [ФАТАЛЬНАЯ ОШИБКА]: все корутины (количество: 1) спят - взаимная блокировка!
===================================================================

Как мне завернуть UDP сервер в корутину? Я думал, что он уже работает как корутина, или я что-то очевидное пропустил?

Ответ или решение

Для решения вашей задачи необходимо правильно обернуть UDP-сервер в корутину и убедиться, что поток не блокируется, создавая мертвую блокировку. Ваша текущая попытка создает ситуацию, при которой корутины ждут данные, которые никогда не будут обработаны, что приводит к ошибке мертвого блока.

Для начала, вы должны перенести настройку сервера в корутину и запускать сервер из этой корутины. Таким образом, вы гарантируете, что сервер и его события будут работать в контексте корутины. Вот исправленный код:

// Создание канала с пространством для 1000 сообщений
$chan = new OpenSwoole\Coroutine\Channel(1000);

co::run(function () use ($chan) {

    // Короутина для сокета UDP
    go(function() use ($chan) {
        // слушатель
        $server = new OpenSwoole\Server('127.0.0.1', 9502, OpenSwoole\Server::POOL_MODE, OpenSwoole\Constant::SOCK_UDP);

        // Установка обработчика для события Packet
        $server->on('Packet', function ($server, $data, $clientInfo) use ($chan) {
            echo ("Data written: $data\n");
            $chan->push($data);
        });

        // Запуск сервера
        $server->start();
    });

    // Чтение из канала
    while (1) {
        $data_read = $chan->pop();
        echo ("Data read: $data_read\n");
    }
});

Объяснение изменений:

  1. Упаковка UDP-сервера в корутину: Мы создали новую корутину, в которой находится весь код, связанный с сервером. Это нужно для того, чтобы избежать блокировок между корутинами и позволить им работать независимо друг от друга.

  2. Запуск сервера: Сервер запускается внутри корутины, что позволяет ему работать в потоке, поддерживаемом библиотекой OpenSwoole.

  3. Проверка данных: Чтение данных из канала также выполняется в корутине, что обеспечивает постоянное получение сообщений, поступающих через UDP.

Теперь, когда вы запустите этот код, сервер будет корректно обрабатывать входящие пакеты и отправлять их в канал для дальнейшей обработки, исключая возможность возникновения мертвого блока.

Оцените материал
Добавить комментарий

Капча загружается...