How to Install and Configure Think‑Worker & GatewayWorker for Real‑Time WebSocket Apps

This guide walks you through installing the Think‑worker extension, setting up GatewayWorker, configuring the server, and creating a simple WebSocket client with HTML and JavaScript to demonstrate real‑time communication using the ThinkPHP framework.

Open Source Tech Hub
Open Source Tech Hub
Open Source Tech Hub
How to Install and Configure Think‑Worker & GatewayWorker for Real‑Time WebSocket Apps

Overview

ThinkPHP

is a lightweight open‑source PHP framework. GatewayWorker extends Workerman to provide TCP long‑connection services (single send, broadcast, group messaging) with built‑in MySQL support and native distributed deployment. think‑worker is the official ThinkPHP extension that integrates Workerman (>=2.0).

Installation

1. Install think‑worker

Run the following Composer command in the project root: composer require topthink/think-worker If you are starting a new ThinkPHP 6 project, create it first:

composer create-project topthink/think tp6
cd tp6
composer require topthink/think-worker

2. Install GatewayWorker

composer require workerman/gateway-worker

Start the gateway process: php think worker:gateway Typical startup output (Workerman 3.5+, PHP 7.4+):

Starting GatewayWorker server...
Workerman[think] start in DEBUG mode
-------------------------------------------- WORKERMAN ---------------------------------------------
Workerman version: 3.5.35   PHP version: 7.4.8   Event-Loop: \Workerman\Events\Select
--------------------------------------------- WORKERS ----------------------------------------------
proto   user    worker    listen                processes   status
tcp     root    Register  text://127.0.0.1:1236   1          [OK]
tcp     root    BusinessWorker  none          1          [OK]
tcp     root    thinkphp  websocket://0.0.0.0:8888   1          [OK]
Press Ctrl+C to stop. Start success.

3. Daemon mode (optional)

php think worker:gateway -d          # run as daemon
php think worker:gateway -H tinywan.com -p 2800   # specify host and port

Configuration

Edit config/gateway_worker.php to match your environment. A minimal configuration is shown below:

<?php
return [
    // Core
    'protocol'   => 'websocket',          // tcp, udp, http, ws, etc.
    'host'       => '0.0.0.0',
    'port'       => 8888,
    'registerAddress' => '127.0.0.1:1236',

    // Gateway settings
    'name'       => 'thinkphp',
    'count'      => 1,
    'lanIp'      => '127.0.0.1',
    'startPort'  => 2000,
    'daemonize'  => false,
    'pingInterval' => 30,
    'pingNotResponseLimit' => 0,
    'pingData'   => '{"type":"ping"}',

    // BusinessWorker settings
    'businessWorker' => [
        'name'        => 'BusinessWorker',
        'count'       => 1,
        // Replace with your own event handler class
        'eventHandler'=> \app\common\Events::class,
    ],
];

The eventHandler class handles all worker callbacks. The default stub is think\worker\Events; replace it with a custom class as demonstrated below.

BusinessWorker Event Class

Create app/common/Events.php (namespace app\common) with the following methods:

<?php
declare(strict_types=1);

namespace app\common;

use GatewayWorker\Lib\Gateway;
use Workerman\Worker;

class Events
{
    /** Called once when a BusinessWorker process starts */
    public static function onWorkerStart(Worker $businessWorker): void {}

    /** Called after TCP handshake */
    public static function onConnect(string $client_id): void
    {
        Gateway::sendToCurrentClient("Your client ID is: $client_id");
    }

    /** Called after WebSocket handshake */
    public static function onWebSocketConnect(string $client_id, $data): void
    {
        var_export($data);
    }

    /** Called when a client sends a message */
    public static function onMessage(string $client_id, $data): void
    {
        Gateway::sendToAll('OpenSourceTech: ' . $data);
    }

    /** Called when a client disconnects */
    public static function onClose(string $client_id): void
    {
        Gateway::sendToAll("client[$client_id] logout
");
    }

    /** Called once when a BusinessWorker process stops */
    public static function onWorkerStop(Worker $businessWorker): void
    {
        echo "WorkerStop
";
    }
}

Local testing with a simple WebSocket client

Save the following HTML as websocket.html and open it in a browser. Replace the placeholder ws://HOST:PORT with the address of the running gateway (e.g., ws://127.0.0.1:8888).

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>GatewayWorker Test</title>
    <style>
        body {font-family: Helvetica, Arial, sans-serif; font-size: 22px;}
        .btn-group {display: inline-block;}
    </style>
</head>
<body onload="init()">
    <input type="text" id="wsaddr" placeholder="ws://..."/>
    <div class="btn-group">
        <button onclick="addsocket()">Connect</button>
        <button onclick="closesocket()">Disconnect</button>
        <button onclick="document.getElementById('wsaddr').value=''">Clear</button>
    </div>
    <div id="output" style="border:1px solid #ccc;height:385px;overflow:auto;margin:20px 0;"></div>
    <input type="text" id="message" placeholder="Message" onkeydown="en(event)"/>
    <button onclick="doSend()">Send</button>

    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
    <script>
        var output, websocket;
        function init() { output = document.getElementById('output'); }
        function addsocket() {
            var wsaddr = $('#wsaddr').val();
            if (!wsaddr) { alert('Please enter a WebSocket address'); return; }
            StartWebSocket(wsaddr);
        }
        function closesocket() { if (websocket) websocket.close(); }
        function StartWebSocket(wsUri) {
            websocket = new WebSocket(wsUri);
            websocket.onopen    = function(e){ writeToScreen('Connected'); };
            websocket.onclose   = function(e){ writeToScreen('Disconnected'); };
            websocket.onmessage = function(e){ writeToScreen('Server: ' + e.data); };
            websocket.onerror   = function(e){ writeToScreen('Error'); };
        }
        function doSend() {
            var msg = $('#message').val();
            if (!msg) { alert('Enter a message'); return; }
            websocket.send(msg);
            writeToScreen('You: ' + msg);
            $('#message').val('');
        }
        function writeToScreen(text) {
            var div = '<div>' + text + '</div>';
            $('#output').append(div);
        }
        function en(e){ if (e.keyCode===13) doSend(); }
    </script>
</body>
</html>

When the server logs show the startup messages and the browser displays “Connected”, the real‑time service is operational.

Ensure that the eventHandler in the configuration points to the custom Events class; otherwise the default stub will be used.

Reference image

GatewayWorker startup screenshot
GatewayWorker startup screenshot
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

WebSocketPHPThinkPHPGatewayWorker
Open Source Tech Hub
Written by

Open Source Tech Hub

Sharing cutting-edge internet technologies and practical AI resources.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.