前端使用的不是socket.io客户端 ,如何实现握手
如果你的前端不使用 socket.io-client,而是使用原生 WebSocket(new WebSocket())或其他普通的 WebSocket 客户端,那么你就不能在 think-swoole 的配置文件中继续使用 socketio 处理器。
因为 socketio 处理器强制要求遵循 Socket.IO 特有的握手(Engine.io)和数据包(Packet)编码协议(例如连接时必须先发送 40,心跳发送 2 和 3,消息带 42 等前缀)。
要使用原生 WebSocket 客户端,你需要切换到 think-swoole 专门提供的原生 WebSocket 模式。
🛠️ 解决方案:切换为原生 WebSocket 模式
1. 修改配置文件
打开 config/swoole.php,将 websocket.handler 改为系统内置的原生 WebSocket 处理器(不要使用 socketio):
php
use think\swoole\websocket\Handler; // 注意:这是原生的 Handler,不是 socketio 目录下的
return [
// ... http 配置保持不变 ...
'websocket' => [
'enable' => true,
'handler' => Handler::class, // 关键:切换回原生处理器
'ping_interval' => 25000,
'ping_timeout' => 60000,
'listen' => [
// 原生模式下,所有接收到的文本消息都会触发这个监听类
'message' => \app\listener\WebsocketMessage::class,
],
'subscribe' => [],
],
];
请谨慎使用此类代码。
2. 创建原生消息监听类
使用命令行生成监听类:
bash
php think make:listener WebsocketMessage
请谨慎使用此类代码。
在 app\listener\WebsocketMessage.php 中编写逻辑。因为是原生模式,前端发送的是纯文本字符串,你需要自行定义通信格式(通常是 JSON):
php
namespace app\listener;
use think\swoole\Websocket;
class WebsocketMessage
{
public function handle(Websocket $websocket, $data)
{
// $data 是前端通过 socket.send() 发送的原生字符串
// 假设前端发送的是 JSON 字符串:{"event": "test", "data": {"name": "ThinkPHP"}}
$payload = json_decode($data, true);
if (!empty($payload['event'])) {
switch ($payload['event']) {
case 'test':
// 回复前端,原生模式下使用 push 发送纯文本
$reply = json_encode([
'event' => 'testcallback',
'data' => ['status' => 'success', 'msg' => '收到原生数据']
]);
$websocket->push($reply);
break;
// 你可以在这里根据 event 字段分发不同的业务逻辑
}
}
}
}
请谨慎使用此类代码。
3. 前端原生客户端连接与握手
原生 WebSocket 的握手是标准的 HTTP Upgrade 协议,由浏览器和 Swoole 自动完成,不需要你手动编写任何握手代码。直接连接即可:
javascript
// 直接连接,不需要任何特殊参数
const ws = new WebSocket("ws://127.0.0.1:9501");
// 监听连接成功(自动完成握手)
ws.onopen = () => {
console.log("WebSocket 连接成功!");
// 发送符合约定的 JSON 字符串
const msg = JSON.stringify({
event: "test",
data: { name: "ThinkPHP" }
});
ws.send(msg);
};
// 监听服务器返回的消息
ws.onmessage = (event) => {
// event.data 是服务器 push 过来的纯文本
const res = JSON.parse(event.data);
console.log("接收到服务器消息:", res);
};
// 监听断开
ws.onclose = () => {
console.log("连接已断开");
};
请谨慎使用此类代码。
💡 核心区别对比
许可协议:
CC BY 4.0