Convert Figma logo to code with AI

walkor logoworkerman

An asynchronous event driven PHP socket framework. Supports HTTP, Websocket, SSL and other custom protocols.

11,091
2,262
11,091
86

Top Related Projects

Event-driven, non-blocking I/O with PHP.

4,217

A non-blocking concurrency framework for PHP applications. 🐘

🚀 Coroutine-based concurrency library for PHP

24,093

Cross-platform asynchronous I/O

106,466

Node.js JavaScript runtime ✨🐢🚀✨

Quick Overview

Workerman is a high-performance PHP socket framework for building fast, scalable network applications. It supports multiple protocols and provides an event-driven, asynchronous programming model for developing real-time applications such as chat servers, game servers, and IoT platforms.

Pros

  • High performance and low resource consumption
  • Easy to use with a simple API
  • Supports multiple protocols (HTTP, WebSocket, TCP, UDP)
  • Cross-platform compatibility (Linux, macOS, Windows)

Cons

  • Requires PHP CLI and some extensions to be installed
  • Limited built-in features compared to full-stack frameworks
  • Learning curve for developers new to asynchronous programming
  • Documentation primarily in Chinese, with limited English resources

Code Examples

  1. Creating a simple HTTP server:
use Workerman\Worker;

$http_worker = new Worker("http://0.0.0.0:2345");
$http_worker->onMessage = function($connection, $data) {
    $connection->send("Hello World!");
};

Worker::runAll();
  1. Implementing a WebSocket server:
use Workerman\Worker;

$ws_worker = new Worker("websocket://0.0.0.0:2346");
$ws_worker->onConnect = function($connection) {
    echo "New connection\n";
};
$ws_worker->onMessage = function($connection, $data) {
    $connection->send("Received: $data");
};

Worker::runAll();
  1. Creating a custom protocol server:
use Workerman\Worker;

$custom_worker = new Worker("tcp://0.0.0.0:2347");
$custom_worker->onMessage = function($connection, $data) {
    if ($data === "ping") {
        $connection->send("pong");
    }
};

Worker::runAll();

Getting Started

  1. Install Workerman using Composer:

    composer require workerman/workerman
    
  2. Create a new PHP file (e.g., server.php) with the following content:

    <?php
    require_once __DIR__ . '/vendor/autoload.php';
    
    use Workerman\Worker;
    
    $worker = new Worker("http://0.0.0.0:8080");
    $worker->onMessage = function($connection, $request) {
        $connection->send("Hello, Workerman!");
    };
    
    Worker::runAll();
    
  3. Run the server:

    php server.php start
    
  4. Access the server at http://localhost:8080 in your web browser.

Competitor Comparisons

Event-driven, non-blocking I/O with PHP.

Pros of ReactPHP

  • More comprehensive ecosystem with a wide range of components
  • Better suited for complex, event-driven applications
  • Stronger focus on asynchronous programming patterns

Cons of ReactPHP

  • Steeper learning curve, especially for developers new to asynchronous programming
  • Can be more complex to set up and configure for simple use cases

Code Comparison

ReactPHP:

$loop = React\EventLoop\Factory::create();
$socket = new React\Socket\Server('127.0.0.1:8080', $loop);
$socket->on('connection', function (React\Socket\ConnectionInterface $conn) {
    $conn->write("Hello ReactPHP!\n");
});
$loop->run();

Workerman:

use Workerman\Worker;

$worker = new Worker('tcp://0.0.0.0:8080');
$worker->onConnect = function($connection) {
    $connection->send("Hello Workerman!\n");
};
Worker::runAll();

Summary

ReactPHP offers a more comprehensive ecosystem for complex, event-driven applications but comes with a steeper learning curve. Workerman, on the other hand, provides a simpler approach that may be more suitable for straightforward use cases. The code comparison illustrates the different approaches to handling connections, with ReactPHP using an event loop and Workerman using a more traditional worker model.

4,217

A non-blocking concurrency framework for PHP applications. 🐘

Pros of amp

  • Built on top of PHP's native event loop, providing better integration with PHP's core functionality
  • Offers a more comprehensive ecosystem with additional libraries for HTTP, WebSockets, and more
  • Provides a more modern and flexible API design, making it easier to write asynchronous code

Cons of amp

  • Steeper learning curve due to its more complex architecture and concepts
  • Smaller community and fewer resources compared to Workerman
  • May have slightly higher overhead in some scenarios due to its abstraction layers

Code Comparison

amp:

Loop::run(function () {
    $server = Socket\listen("0.0.0.0:1337");
    while ($socket = yield $server->accept()) {
        $client = new Client($socket);
        $client->onData(function ($data) use ($client) {
            $client->write("Hello " . $data);
        });
    }
});

Workerman:

$worker = new Worker("tcp://0.0.0.0:1337");
$worker->onMessage = function($connection, $data) {
    $connection->send("Hello " . $data);
};
Worker::runAll();

Both examples demonstrate a simple TCP server, but amp uses a more explicit asynchronous approach with generators and yields, while Workerman provides a more straightforward event-driven API.

🚀 Coroutine-based concurrency library for PHP

Pros of Swoole

  • Higher performance due to its C-based implementation and asynchronous I/O
  • Built-in support for WebSocket, HTTP/2, and TCP/UDP protocols
  • Offers coroutine-based concurrency for easier asynchronous programming

Cons of Swoole

  • Requires PHP extension installation, which can be complex on some systems
  • Steeper learning curve due to its more advanced features and concepts
  • Less compatible with traditional PHP applications and frameworks

Code Comparison

Workerman example:

use Workerman\Worker;

$worker = new Worker('websocket://0.0.0.0:2345');
$worker->onMessage = function($connection, $data) {
    $connection->send('Hello ' . $data);
};
Worker::runAll();

Swoole example:

$server = new Swoole\WebSocket\Server('0.0.0.0', 9501);
$server->on('message', function ($server, $frame) {
    $server->push($frame->fd, 'Hello ' . $frame->data);
});
$server->start();

Both examples demonstrate a simple WebSocket server, but Swoole's implementation is more concise and leverages its built-in WebSocket support. Workerman's approach is more traditional and easier to understand for PHP developers new to asynchronous programming.

24,093

Cross-platform asynchronous I/O

Pros of libuv

  • Cross-platform support for asynchronous I/O
  • Widely used and battle-tested in major projects like Node.js
  • Lower-level API offering more fine-grained control

Cons of libuv

  • Steeper learning curve due to its C-based API
  • Requires more boilerplate code for basic operations
  • Less abstraction, which can lead to more complex code for simple tasks

Code Comparison

libuv (C):

uv_loop_t *loop = malloc(sizeof(uv_loop_t));
uv_loop_init(loop);
uv_tcp_t server;
uv_tcp_init(loop, &server);
uv_run(loop, UV_RUN_DEFAULT);

Workerman (PHP):

use Workerman\Worker;

$worker = new Worker('tcp://0.0.0.0:8080');
$worker->onMessage = function($connection, $data) {
    $connection->send('Hello');
};
Worker::runAll();

Key Differences

  • libuv is a C library, while Workerman is PHP-based
  • libuv provides lower-level control, Workerman offers higher-level abstractions
  • Workerman is specifically designed for PHP network programming, while libuv is language-agnostic and used in various projects
  • libuv requires manual memory management, whereas Workerman leverages PHP's garbage collection

Both libraries serve different purposes and target different developer audiences, making direct comparison challenging in some aspects.

106,466

Node.js JavaScript runtime ✨🐢🚀✨

Pros of Node.js

  • Larger ecosystem with more packages and libraries available
  • Better performance for I/O-intensive operations due to its event-driven, non-blocking architecture
  • More extensive documentation and community support

Cons of Node.js

  • Higher memory usage compared to Workerman
  • Steeper learning curve for developers new to asynchronous programming
  • Less efficient for CPU-bound tasks due to its single-threaded nature

Code Comparison

Node.js:

const http = require('http');

const server = http.createServer((req, res) => {
  res.writeHead(200, { 'Content-Type': 'text/plain' });
  res.end('Hello World\n');
});

server.listen(8080);

Workerman:

use Workerman\Worker;

$http_worker = new Worker("http://0.0.0.0:8080");
$http_worker->onMessage = function($connection, $data) {
    $connection->send('Hello World');
};

Worker::runAll();

Both examples create a simple HTTP server listening on port 8080 and responding with "Hello World". Node.js uses its built-in http module, while Workerman uses its Worker class. The Node.js version is more concise, but Workerman's approach may be more intuitive for PHP developers.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

Workerman

Gitter Latest Stable Version Total Downloads Monthly Downloads Daily Downloads License

What is it

Workerman is an asynchronous event-driven PHP framework with high performance to build fast and scalable network applications. Workerman supports HTTP, Websocket, SSL and other custom protocols. Workerman supports event extension.

Requires

A POSIX compatible operating system (Linux, OSX, BSD)
POSIX and PCNTL extensions required
Event extension recommended for better performance

Installation

composer require workerman/workerman

Documentation

https://manual.workerman.net

Basic Usage

A websocket server

<?php

use Workerman\Worker;

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

// Create a Websocket server
$ws_worker = new Worker('websocket://0.0.0.0:2346');

// Emitted when new connection come
$ws_worker->onConnect = function ($connection) {
    echo "New connection\n";
};

// Emitted when data received
$ws_worker->onMessage = function ($connection, $data) {
    // Send hello $data
    $connection->send('Hello ' . $data);
};

// Emitted when connection closed
$ws_worker->onClose = function ($connection) {
    echo "Connection closed\n";
};

// Run worker
Worker::runAll();

An http server

use Workerman\Worker;

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

// #### http worker ####
$http_worker = new Worker('http://0.0.0.0:2345');

// 4 processes
$http_worker->count = 4;

// Emitted when data received
$http_worker->onMessage = function ($connection, $request) {
    //$request->get();
    //$request->post();
    //$request->header();
    //$request->cookie();
    //$request->session();
    //$request->uri();
    //$request->path();
    //$request->method();

    // Send data to client
    $connection->send("Hello World");
};

// Run all workers
Worker::runAll();

A tcp server

use Workerman\Worker;

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

// #### create socket and listen 1234 port ####
$tcp_worker = new Worker('tcp://0.0.0.0:1234');

// 4 processes
$tcp_worker->count = 4;

// Emitted when new connection come
$tcp_worker->onConnect = function ($connection) {
    echo "New Connection\n";
};

// Emitted when data received
$tcp_worker->onMessage = function ($connection, $data) {
    // Send data to client
    $connection->send("Hello $data \n");
};

// Emitted when connection is closed
$tcp_worker->onClose = function ($connection) {
    echo "Connection closed\n";
};

Worker::runAll();

Enable SSL

<?php

use Workerman\Worker;

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

// SSL context.
$context = [
    'ssl' => [
        'local_cert'  => '/your/path/of/server.pem',
        'local_pk'    => '/your/path/of/server.key',
        'verify_peer' => false,
    ]
];

// Create a Websocket server with ssl context.
$ws_worker = new Worker('websocket://0.0.0.0:2346', $context);

// Enable SSL. WebSocket+SSL means that Secure WebSocket (wss://). 
// The similar approaches for Https etc.
$ws_worker->transport = 'ssl';

$ws_worker->onMessage = function ($connection, $data) {
    // Send hello $data
    $connection->send('Hello ' . $data);
};

Worker::runAll();

Custom protocol

Protocols/MyTextProtocol.php


namespace Protocols;

/**
 * User defined protocol
 * Format Text+"\n"
 */
class MyTextProtocol
{
    public static function input($recv_buffer)
    {
        // Find the position of the first occurrence of "\n"
        $pos = strpos($recv_buffer, "\n");

        // Not a complete package. Return 0 because the length of package can not be calculated
        if ($pos === false) {
            return 0;
        }

        // Return length of the package
        return $pos + 1;
    }

    public static function decode($recv_buffer)
    {
        return trim($recv_buffer);
    }

    public static function encode($data)
    {
        return $data . "\n";
    }
}
use Workerman\Worker;

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

// #### MyTextProtocol worker ####
$text_worker = new Worker('MyTextProtocol://0.0.0.0:5678');

$text_worker->onConnect = function ($connection) {
    echo "New connection\n";
};

$text_worker->onMessage = function ($connection, $data) {
    // Send data to client
    $connection->send("Hello world\n");
};

$text_worker->onClose = function ($connection) {
    echo "Connection closed\n";
};

// Run all workers
Worker::runAll();

Timer


use Workerman\Worker;
use Workerman\Timer;

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

$task = new Worker();
$task->onWorkerStart = function ($task) {
    // 2.5 seconds
    $time_interval = 2.5; 
    $timer_id = Timer::add($time_interval, function () {
        echo "Timer run\n";
    });
};

// Run all workers
Worker::runAll();

AsyncTcpConnection (tcp/ws/text/frame etc...)


use Workerman\Worker;
use Workerman\Connection\AsyncTcpConnection;

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

$worker = new Worker();
$worker->onWorkerStart = function () {
    // Websocket protocol for client.
    $ws_connection = new AsyncTcpConnection('ws://echo.websocket.org:80');
    $ws_connection->onConnect = function ($connection) {
        $connection->send('Hello');
    };
    $ws_connection->onMessage = function ($connection, $data) {
        echo "Recv: $data\n";
    };
    $ws_connection->onError = function ($connection, $code, $msg) {
        echo "Error: $msg\n";
    };
    $ws_connection->onClose = function ($connection) {
        echo "Connection closed\n";
    };
    $ws_connection->connect();
};

Worker::runAll();

Use HTTP proxy

<?php

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

use Workerman\Connection\AsyncTcpConnection;
$worker = new \Workerman\Worker();
$worker->onWorkerStart = function($worker){
    echo '开始链接' . PHP_EOL;
    $url = 'ws://stream.binance.com:9443/ws';
    $con = new AsyncTcpConnection($url);
    $con->transport = 'ssl';
//    $con->proxySocks5 = '127.0.0.1:1080';
    $con->proxyHttp = '127.0.0.1:25378';

    $con->onConnect = function(AsyncTcpConnection $con) {
        $ww = [
            'id' => 1,
            'method' => 'SUBSCRIBE',
            'params' => [
                "btcusdt@aggTrade",
                "btcusdt@depth"
            ]
        ];
        echo '链接成功';
        $con->send(json_encode($ww));
        echo 'ok';
    };

    $con->onMessage = function(AsyncTcpConnection $con, $data) {
        echo $data;
    };

    $con->onClose = function (AsyncTcpConnection $con) {
        echo 'onClose' . PHP_EOL;
    };

    $con->onError = function (AsyncTcpConnection $con, $code, $msg) {
        echo "error [ $code ] $msg\n";
    };

    $con->connect();
};
\Workerman\Worker::runAll();

Use Socks5 proxy

<?php

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

use Workerman\Connection\AsyncTcpConnection;
$worker = new \Workerman\Worker();
$worker->onWorkerStart = function($worker){
    echo '开始链接' . PHP_EOL;
    $url = 'ws://stream.binance.com:9443/ws';
    $con = new AsyncTcpConnection($url);
    $con->transport = 'ssl';
    $con->proxySocks5 = '127.0.0.1:1080';
//    $con->proxyHttp = '127.0.0.1:25378';

    $con->onConnect = function(AsyncTcpConnection $con) {
        $ww = [
            'id' => 1,
            'method' => 'SUBSCRIBE',
            'params' => [
                "btcusdt@aggTrade",
                "btcusdt@depth"
            ]
        ];
        echo '链接成功';
        $con->send(json_encode($ww));
        echo 'ok';
    };

    $con->onMessage = function(AsyncTcpConnection $con, $data) {
        echo $data;
    };

    $con->onClose = function (AsyncTcpConnection $con) {
        echo 'onClose' . PHP_EOL;
    };

    $con->onError = function (AsyncTcpConnection $con, $code, $msg) {
        echo "error [ $code ] $msg\n";
    };

    $con->connect();
};
\Workerman\Worker::runAll();

proxy supports TLS1.3, no Sniproxy channel

Available commands

php start.php start
php start.php start -d
php start.php status
php start.php status -d
php start.php connections
php start.php stop
php start.php stop -g
php start.php restart
php start.php reload
php start.php reload -g

Benchmarks

https://www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=plaintext&l=zik073-1r

Other links with workerman

webman
AdapterMan

Donate

PayPal

LICENSE

Workerman is released under the MIT license.