技术 2026年06月18日 👤 mdo 👁 4 阅读

前端使用的不是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("连接已断开");
};

请谨慎使用此类代码。


💡 核心区别对比

功能特性

Socket.IO 模式 (socketio\Handler)

原生 WebSocket 模式 (Handler)

前端客户端

必须用 socket.io-client

任何支持 WebSocket 的工具(如 new WebSocket)

握手机制

复杂的自定义 HTTP 轮询/升级(含 sid 校验)

标准的 HTTP Upgrade(浏览器自动处理)

数据格式

内置事件机制(emit 路由,自带包前缀)

纯文本/二进制(需要自己 json_decode)

后端回复方法

$websocket->emit()

$websocket->push()