PHP code example of easyswoole / socket

1. Go to this page and download the library: Download easyswoole/socket library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

easyswoole / socket example snippets




use EasySwoole\Socket\AbstractInterface\ParserInterface;
use EasySwoole\Socket\Bean\Caller;
use EasySwoole\Socket\Bean\Response;
use EasySwoole\Socket\Client\Tcp;
use EasySwoole\Socket\Client\Udp;

final class JsonParser implements ParserInterface
{
    public function decode(string $raw, Tcp|Udp $client): ?Caller
    {
        $payload = json_decode($raw, true, flags: JSON_THROW_ON_ERROR);

        $caller = new Caller();
        $caller->setControllerClass(EchoController::class);
        $caller->setAction($payload['action'] ?? null);
        $caller->setArgs($payload['args'] ?? []);

        return $caller;
    }

    public function encode(Response $response, Tcp|Udp $client): ?string
    {
        return json_encode(
            ['message' => $response->getMessage()],
            JSON_THROW_ON_ERROR
        );
    }
}



use EasySwoole\Socket\AbstractInterface\Controller;
use EasySwoole\Socket\Client\Tcp;
use EasySwoole\Socket\Client\WebSocket;
use EasySwoole\Socket\Enum\ResponseStatus;

final class EchoController extends Controller
{
    protected function onRequest(?string $actionName): bool
    {
        return true;
    }

    public function echo(): void
    {
        $this->response()->setMessage([
            'args' => $this->caller()->getArgs(),
            'client' => $this->clientInformation(),
        ]);
    }

    public function notify(): void
    {
        $sent = $this->responseImmediately('notification');
        if (!$sent) {
            // 由业务层决定记录、重试或忽略。
        }

        $this->response()->setStatus(ResponseStatus::WITHOUT_RESPONSE);
    }

    protected function actionNotFound(?string $actionName): void
    {
        $this->response()->setMessage(['error' => 'action not found']);
    }

    protected function afterAction(?string $actionName): void
    {
        // action 成功、失败或被拦截后都会执行。
    }

    private function clientInformation(): array
    {
        $client = $this->caller()->getClient();

        if ($client instanceof WebSocket) {
            return [
                'type' => 'websocket',
                'fd' => $client->getFd(),
                'data' => $client->getData(),
                'opcode' => $client->getOpCode(),
                'finish' => $client->getIsFinish(),
            ];
        }

        if ($client instanceof Tcp) {
            return [
                'type' => 'tcp',
                'fd' => $client->getFd(),
                'reactorId' => $client->getReactorId(),
            ];
        }

        return [
            'type' => 'udp',
            'serverSocket' => $client->getServerSocket(),
            'address' => $client->getAddress(),
            'port' => $client->getPort(),
        ];
    }
}

use EasySwoole\Socket\Config;
use EasySwoole\Socket\Enum\SocketType;

$config = new Config(SocketType::TCP, new JsonParser());

use EasySwoole\Socket\Bean\Response;
use EasySwoole\Socket\Client\Tcp;
use EasySwoole\Socket\Client\Udp;
use EasySwoole\Socket\Enum\ResponseStatus;
use Swoole\Server;

$config->setOnExceptionHandler(
    function (
        Server $server,
        Throwable $throwable,
        string $raw,
        Tcp|Udp $client,
        Response $response
    ): void {
        $response->setMessage(['error' => $throwable->getMessage()]);
        $response->setStatus(ResponseStatus::RESPONSE_AND_CLOSE);
    }
);

$response->setStatus(ResponseStatus::WITHOUT_RESPONSE);

$response->setReset(true);
$response->setStatus(ResponseStatus::CLOSE);

$response->setCode(SWOOLE_WEBSOCKET_CLOSE_NORMAL);
$response->setReason('normal closure');
$response->setStatus(ResponseStatus::RESPONSE_AND_CLOSE);

$response->setOpCode(WEBSOCKET_OPCODE_BINARY);
$response->setFlags(
    SWOOLE_WEBSOCKET_FLAG_FIN | SWOOLE_WEBSOCKET_FLAG_COMPRESS
);



use EasySwoole\Socket\Config;
use EasySwoole\Socket\Dispatcher;
use EasySwoole\Socket\Enum\SocketType;
use Swoole\Server;

$server = new Server('127.0.0.1', 9501);
$server->set(['worker_num' => 1]);

$dispatcher = new Dispatcher(
    new Config(SocketType::TCP, new JsonParser())
);

$server->on(
    'receive',
    function (Server $server, int $fd, int $reactorId, string $data) use ($dispatcher): void {
        $dispatcher->dispatchTcp($server, $data, $fd, $reactorId);
    }
);

$server->start();

$server->set([
    'worker_num' => 1,
    'open_length_check' => true,
    'package_length_type' => 'N',
    'package_length_offset' => 0,
    'package_body_offset' => 4,
    'package_max_length' => 4 * 1024 * 1024,
]);

use EasySwoole\Socket\Tools\Protocol;

$packet = Protocol::pack('payload');
$payload = Protocol::unpack($packet);

use EasySwoole\Socket\Bean\Caller;
use EasySwoole\Socket\Client\Tcp;
use EasySwoole\Socket\Client\Udp;
use EasySwoole\Socket\Client\WebSocket;
use EasySwoole\Socket\Tools\Protocol;

public function decode(string $raw, Tcp|Udp $client): ?Caller
{
    if ($client instanceof Tcp && !$client instanceof WebSocket) {
        $raw = Protocol::unpack($raw);
    }

    $payload = json_decode($raw, true, flags: JSON_THROW_ON_ERROR);
    // 根据业务协议创建 Caller。
}

public function encode(Response $response, Tcp|Udp $client): ?string
{
    $body = json_encode(
        ['message' => $response->getMessage()],
        JSON_THROW_ON_ERROR
    );

    return Protocol::pack($body);
}

use EasySwoole\Socket\Tools\Client;
use Swoole\Coroutine;

Coroutine\run(function (): void {
    $client = new Client(
        unixSock: '127.0.0.1',
        port: 9501,
        timeout: 3.0,
        maxPackageLength: 4 * 1024 * 1024
    );

    // send() 会自动使用 Protocol::pack() 添加 4 字节长度头。
    $sentBytes = $client->send(
        json_encode([
            'action' => 'echo',
            'args' => ['message' => 'hello'],
        ], JSON_THROW_ON_ERROR),
        safeSend: true,
        timeout: 3.0
    );

    if ($sentBytes === false) {
        throw new RuntimeException('send failed');
    }

    // recv() 会等待完整数据包并自动移除 4 字节长度头。
    $rawResponse = $client->recv(timeout: 3.0);
    if ($rawResponse !== null) {
        $response = json_decode($rawResponse, true, flags: JSON_THROW_ON_ERROR);
        var_dump($response);
    }

    $client->close();
});



use EasySwoole\Socket\Config;
use EasySwoole\Socket\Dispatcher;
use EasySwoole\Socket\Enum\SocketType;
use Swoole\Server;

$server = new Server('127.0.0.1', 9502, SWOOLE_PROCESS, SWOOLE_SOCK_UDP);
$dispatcher = new Dispatcher(
    new Config(SocketType::UDP, new JsonParser())
);

$server->on(
    'packet',
    function (Server $server, string $data, array $clientInfo) use ($dispatcher): void {
        $dispatcher->dispatchUdp(
            $server,
            $data,
            $clientInfo['server_socket'],
            $clientInfo['address'],
            $clientInfo['port']
        );
    }
);

$server->start();



use EasySwoole\Socket\Config;
use EasySwoole\Socket\Dispatcher;
use EasySwoole\Socket\Enum\SocketType;
use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server;

$server = new Server('127.0.0.1', 9503);
$dispatcher = new Dispatcher(
    new Config(SocketType::WEB_SOCKET, new JsonParser())
);

$server->on(
    'message',
    function (Server $server, Frame $frame) use ($dispatcher): void {
        $dispatcher->dispatchWebSocket($server, $frame);
    }
);

$server->start();

use EasySwoole\Socket\Tools\Protocol;

$packet = Protocol::pack('payload');
$payload = Protocol::unpack($packet);

$payload = Protocol::socketReader(
    $socket,
    timeout: 3.0,
    maxPackageLength: 4 * 1024 * 1024
);

use EasySwoole\Socket\Tools\Client;
use Swoole\Coroutine;

Coroutine\run(function (): void {
    $client = new Client('/tmp/example.sock');
    $client->send('request');
    $response = $client->recv();
    $client->close();
});

use EasySwoole\Socket\Tools\Client;
use Swoole\Coroutine;

Coroutine\run(function (): void {
    $client = new Client(
        unixSock: '127.0.0.1',
        port: 9501,
        timeout: 3.0,
        maxPackageLength: 4 * 1024 * 1024
    );
});