本文目录导读:

在 PHP 中实现 WebSocket 服务有几种方式,下面我来详细介绍。
使用 Workerman(推荐)
Workerman 是最流行的 PHP WebSocket 解决方案。
安装
composer require workerman/workerman
基本示例
<?php
use Workerman\Worker;
use Workerman\Connection\TcpConnection;
require_once __DIR__ . '/vendor/autoload.php';
// 创建 WebSocket 服务,监听 2346 端口
$ws_worker = new Worker("websocket://0.0.0.0:2346");
// 设置进程数
$ws_worker->count = 4;
// 客户端连接时触发
$ws_worker->onConnect = function(TcpConnection $connection) {
echo "新连接建立\n";
};
// 收到客户端消息时触发
$ws_worker->onMessage = function(TcpConnection $connection, $data) {
echo "收到消息: $data\n";
// 发送消息给客户端
$connection->send("服务器收到: $data");
// 广播给所有客户端
foreach ($connection->worker->connections as $client) {
$client->send("广播消息: $data");
}
};
// 客户端断开时触发
$ws_worker->onClose = function(TcpConnection $connection) {
echo "连接关闭\n";
};
// 启动服务
Worker::runAll();
运行方式
# 启动服务(前台运行) php websocket.php start # 后台运行 php websocket.php start -d # 停止服务 php websocket.php stop
使用 Ratchet
Ratchet 是另一个常用的 WebSocket 库。
安装
composer require cboden/ratchet
基本示例
<?php
use Ratchet\MessageComponentInterface;
use Ratchet\ConnectionInterface;
use Ratchet\Http\HttpServer;
use Ratchet\Server\IoServer;
use Ratchet\WebSocket\WsServer;
require_once __DIR__ . '/vendor/autoload.php';
class Chat implements MessageComponentInterface {
protected $clients;
public function __construct() {
$this->clients = new \SplObjectStorage;
}
// 客户端连接
public function onOpen(ConnectionInterface $conn) {
$this->clients->attach($conn);
echo "新连接: {$conn->resourceId}\n";
}
// 接收消息
public function onMessage(ConnectionInterface $from, $msg) {
echo "收到消息: $msg\n";
// 广播给所有客户端
foreach ($this->clients as $client) {
if ($from !== $client) {
$client->send($msg);
}
}
}
// 关闭连接
public function onClose(ConnectionInterface $conn) {
$this->clients->detach($conn);
echo "连接关闭\n";
}
// 错误处理
public function onError(ConnectionInterface $conn, \Exception $e) {
echo "错误: {$e->getMessage()}\n";
$conn->close();
}
}
// 创建服务
$server = IoServer::factory(
new HttpServer(
new WsServer(
new Chat()
)
),
8080
);
echo "WebSocket 服务器运行在端口 8080\n";
$server->run();
运行方式
php chat-server.php
原生 PHP WebSocket 实现
如果不想使用第三方库,也可以原生实现(比较复杂):
<?php
class WebSocketServer {
private $clients = [];
private $socket;
public function __construct($host, $port) {
$this->socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
socket_set_option($this->socket, SOL_SOCKET, SO_REUSEADDR, 1);
socket_bind($this->socket, $host, $port);
socket_listen($this->socket);
echo "WebSocket 服务器运行在 $host:$port\n";
}
public function run() {
while (true) {
$read = $this->clients;
$read[] = $this->socket;
socket_select($read, $write, $except, null);
// 新连接
if (in_array($this->socket, $read)) {
$newClient = socket_accept($this->socket);
$this->handshake($newClient);
$this->clients[] = $newClient;
}
// 处理客户端消息
foreach ($read as $client) {
if ($client === $this->socket) continue;
$data = @socket_read($client, 1024);
if ($data) {
$data = $this->decode($data);
echo "收到: $data\n";
// 广播给所有客户端
foreach ($this->clients as $c) {
if ($c !== $client) {
socket_write($c, $this->encode($data));
}
}
} else {
// 客户端断开
$index = array_search($client, $this->clients);
unset($this->clients[$index]);
socket_close($client);
}
}
}
}
// WebSocket 握手
private function handshake($client) {
$request = socket_read($client, 1024);
preg_match('/Sec-WebSocket-Key:\s(.*)\r\n/', $request, $matches);
$key = $matches[1] ?? '';
$accept = base64_encode(sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));
$response = "HTTP/1.1 101 Switching Protocols\r\n"
. "Upgrade: websocket\r\n"
. "Connection: Upgrade\r\n"
. "Sec-WebSocket-Accept: $accept\r\n\r\n";
socket_write($client, $response);
}
// 解码客户端消息
private function decode($payload) {
$length = ord($payload[1]) & 127;
$mask = substr($payload, 2, 4);
$data = substr($payload, 6);
$decoded = '';
for ($i = 0; $i < strlen($data); $i++) {
$decoded .= $data[$i] ^ $mask[$i % 4];
}
return $decoded;
}
// 编码发送给客户端的消息
private function encode($data) {
$payload = '81';
$len = strlen($data);
if ($len <= 125) {
$payload .= sprintf('%02X', $len);
} elseif ($len <= 65535) {
$payload .= '7E' . sprintf('%04X', $len);
} else {
$payload .= '7F' . sprintf('%08X', $len);
}
$payload .= bin2hex($data);
return hex2bin($payload);
}
}
// 使用
$server = new WebSocketServer('0.0.0.0', 8080);
$server->run();
客户端示例(JavaScript)
// 连接 WebSocket
const ws = new WebSocket('ws://localhost:2346');
// 连接建立时
ws.onopen = function() {
console.log('连接成功');
ws.send('Hello Server!');
};
// 接收消息
ws.onmessage = function(event) {
console.log('收到服务器消息:', event.data);
};
// 关闭连接
ws.onclose = function() {
console.log('连接关闭');
};
// 错误处理
ws.onerror = function(error) {
console.error('错误:', error);
};
推荐方案对比
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| Workerman | 性能好、功能全、文档丰富 | 需要 PHP CLI 环境 | 生产环境、高性能需求 |
| Ratchet | 简单易用、纯 PHP | 性能一般 | 中小型项目 |
| 原生实现 | 无依赖 | 复杂、容易出错 | 学习研究 |
部署注意事项
- 使用 PHP CLI 模式:WebSocket 服务需要长驻内存,不能使用 PHP-FPM
- 防火墙配置:确保 WebSocket 端口对外开放
- 反向代理:可以使用 Nginx 反向代理 WebSocket
- SSL 支持:生产环境建议使用 WSS(WebSocket Secure)
如果需要更多帮助,请告诉我你的具体使用场景!
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播