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.
Overview
ThinkPHPis 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-worker2. Install GatewayWorker
composer require workerman/gateway-workerStart 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 portConfiguration
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
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Open Source Tech Hub
Sharing cutting-edge internet technologies and practical AI resources.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
