使用workerman实现UDP服务器

<?php
// UDP服务端文件:workerman.udp.server.php
declare(strict_types=1);
ini_set('display_errors', 'On');
error_reporting(-1);
set_time_limit(0);
PHP_SAPI === 'cli' || exit('脚本只能在命令行执行');

use Workerman\Worker;
use Workerman\Connection\UdpConnection;

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

function v(mixed $value, mixed ...$values): void
{
    ob_start();
    var_dump($value);
    echo ob_get_clean();

    foreach ($values as $v) {
        v($v);
    }
}

function datetime(): string
{
    return date('Y-m-d H:i:s');
}

$worker = new Worker('udp://127.0.0.1:9292');

echo '[' . datetime() . '][INFO] Socket Name: ' . $worker->getSocketName() . PHP_EOL;

$worker->onMessage = static function (UdpConnection $udpConnection, string $data) {
    echo '[' . datetime() . "][ONMESSAGE] $data" . PHP_EOL;

    // 休眠一段时间后才向客户端返回(三条)消息
    sleep(3);
    $udpConnection->send('从入门到放弃-1');
    sleep(3);
    $udpConnection->send('从入门到放弃-2');
    sleep(3);
    $udpConnection->send('从入门到放弃-3');
};

Worker::runAll();

//========== 启动UDP服务器命令 ==========//
// [root@localhost ~]# /program/php/bin/php /inetpub/wwwroot/demo/workerman.udp.server.php start

//========== 总结 ==========//
// 1、UDP是无连接的,所以UDP服务没有onConnect和onClose事件。



<?php
// UDP客户端文件:workerman.udp.client.php
declare(strict_types=1);
ini_set('display_errors', 'On');
error_reporting(-1);
set_time_limit(0);

// UDP服务器主机地址和端口号
$address = '127.0.0.1';
$port = 9292;

$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);

// 设置接收超时时间
$option = ['sec' => 2, 'usec' => 0]; // sec是超时时间的秒部分,usec是微秒部分
socket_set_option($socket, SOL_SOCKET, SO_RCVTIMEO, $option);

$sendto = 'PHP是世界上最好的语言'; // 要发送给UDP服务器的数据
$hex = bin2hex($sendto); // 转为十六进制
$bin = hex2bin($hex); // 转为二进制字
socket_sendto($socket, $bin, 1024, 0, $address, $port);

$endTime = time() + 10;

while (true) {
    $data = '';

    // socket_recvfrom()会报Warning错误,需要临时屏蔽Warning错误,执行完socket_recvfrom()再恢复
    $errorReportingOld = error_reporting();
    error_reporting($errorReportingOld & ~E_WARNING); // 临时屏蔽Warning错误
    socket_recvfrom($socket, $data, 1024, 0, $address, $port);
    error_reporting($errorReportingOld); // 恢复原来的error_reporting设置

    if ($data !== '') {
        echo var_export($data, true) . PHP_EOL;
    }

    if (time() > $endTime) {
        break;
    }
}

socket_close($socket);

Copyright © 2024 码农人生. All Rights Reserved