avatar

mdo

Hello

  • 首页
  • 知识库
  • 归档
  • 标签
  • 关于
主页 前端使用的不是socket.io客户端 ,如何实现握手
文章

前端使用的不是socket.io客户端 ,如何实现握手

发表于 2026-06-18 更新于 2026-06- 18
作者 mdo
21~27 分钟 阅读

如果你的前端不使用 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()

技术
许可协议:  CC BY 4.0
分享

相关文章

7月 26, 2026

完美地解决 TP3 老系统数据的平滑读取

为了彻底、完美地解决 TP3 老系统数据的平滑读取,必须解决两个核心痛点: TP3 的盲猜反序列化机制(标量存原样,数组/对象存原生 serialize,同时兼容 json)。 TP3 与 TP6 的缓存前缀(Prefix)不一致。 以下是为你量身定制的终极落地解决方案,通

7月 26, 2026

thinkphp3 redis序列化和反序列化

在老系统重构迁移至 ThinkPHP 6 (TP6) 的过程中,ThinkPHP 3 (TP3) 的 Redis 序列化历史遗留问题是最核心的连环坑之一。 TP3 的 S('key', $value) 缓存方法和底层 Redis 驱动,在存储非字符串(如数组、对象)时,有一套独特的序列化行为。如果不

7月 24, 2026

Table 空间极易发生哈希冲突并溢出

既然你没有在业务中主动调用 Room,只使用了全局广播,那么这个问题就非常明确了:即使你不用房间功能,think-swoole 只要开启了 WebSocket,底层就会强行初始化并注入一个名为 Room 的驱动组件。 [1] 框架底层默认使用 table 类型来作为 Room 的存储介质。当进行全局

下一篇

ubuntu 自定义指令 执行脚本

上一篇

在原生 WebSocket 模式下,增加握手验证逻辑

最近更新

  • 完美地解决 TP3 老系统数据的平滑读取
  • thinkphp3 redis序列化和反序列化
  • Table 空间极易发生哈希冲突并溢出
  • 将监控程序直接跑在云端
  • AI 驱动型 Facebook 群组关键词监控 Chrome 浏览器插件

热门标签

API CodeGeex Gitkraken Management Manticore Premiere Sublime Swoole ThinkPHP ThinkPHP5

目录

©2026 mdo. 保留部分权利。