0

0

Swoole的WebSocket如何使用?WebSocket如何通信?

星降

星降

发布时间:2025-08-18 18:39:01

|

189人浏览过

|

来源于php中文网

原创

swoole的websocket通过封装底层细节,使开发者只需关注open、message、close等事件处理,即可实现全双工通信,区别于http的请求-响应模式,websocket支持服务器主动推送,适用于实时场景。

swoole的websocket如何使用?websocket如何通信?

Swoole的WebSocket用起来,其实比你想象的要直接得多,它把很多底层复杂的网络通信细节都封装好了,你主要就是关注事件处理。而WebSocket通信本身,它就是一种在单个TCP连接上进行全双工通信的协议,一旦握手成功,客户端和服务器就能双向自由发送数据,这跟传统的HTTP那种请求-响应模式完全不一样。

解决方案

要用Swoole搭建一个WebSocket服务器,核心就是监听几个关键事件。首先,你得创建一个

Swoole\WebSocket\Server
实例,指定监听的IP和端口。

<?php
$server = new Swoole\WebSocket\Server("0.0.0.0", 9501);

// 当WebSocket客户端与服务器建立连接并完成握手时
$server->on('open', function (Swoole\WebSocket\Server $server, $request) {
    echo "客户端 {$request->fd} 已连接。\n";
    $server->push($request->fd, "欢迎,你是第 {$request->fd} 位用户!");
});

// 当服务器收到WebSocket客户端发送的数据帧时
$server->on('message', function (Swoole\WebSocket\Server $server, $frame) {
    echo "收到客户端 {$frame->fd} 的消息: {$frame->data}\n";

    // 假设我们想把收到的消息原样发回给发送者
    $server->push($frame->fd, "服务器回应: " . $frame->data);

    // 如果是广播,可以遍历所有连接的fd并push
    // foreach ($server->connections as $fd) {
    //     if ($server->isEstablished($fd)) { // 检查连接是否仍然存在
    //         $server->push($fd, "广播消息: " . $frame->data);
    //     }
    // }
});

// 当WebSocket客户端连接关闭时
$server->on('close', function (Swoole\WebSocket\Server $server, $fd) {
    echo "客户端 {$fd} 已断开连接。\n";
});

// 启动服务器
$server->start();
?>

这段代码基本上涵盖了最基础的WebSocket服务器功能。

onOpen
事件在客户端连接并完成WebSocket握手时触发,你可以在这里做一些初始化工作,比如记录用户上线、发送欢迎消息。
onMessage
是核心,所有客户端发来的数据都会在这里处理,你可以根据
$frame->data
来决定如何响应,比如转发、存储或者执行某些业务逻辑。
onClose
则是在客户端断开连接时触发,可以用来清理资源或者通知其他用户。

客户端方面,用JavaScript就很方便:

// 假设你的Swoole WebSocket服务器运行在localhost:9501
const ws = new WebSocket('ws://localhost:9501');

ws.onopen = function(event) {
    console.log('WebSocket连接已建立!');
    ws.send('你好,Swoole!我是客户端。');
};

ws.onmessage = function(event) {
    console.log('收到服务器消息:', event.data);
};

ws.onclose = function(event) {
    console.log('WebSocket连接已关闭。');
};

ws.onerror = function(error) {
    console.error('WebSocket发生错误:', error);
};

// 你可以随时发送消息
// ws.send('这是另一条消息。');

这样,一个基本的Swoole WebSocket应用就跑起来了。

WebSocket和HTTP有什么本质区别?

聊到WebSocket,很多人会下意识地把它和HTTP拿来比较,毕竟它们都跑在TCP上。但说实话,它们的“性格”完全不同。HTTP,你把它想象成一个“问答机器人”,你问一句,它答一句,然后连接就可能断了(或者保持短时间活跃,但下一句问答还是新的请求-响应周期)。每次问答,都得带上请求头、响应头这些“开场白”,挺啰嗦的。它的核心是“请求-响应”模型,无状态,每次通信都是独立的。

WebSocket则完全是另一种玩法,它更像是一条“专线电话”。一旦电话接通(完成握手),这条线就一直保持着,双方可以随时随地、不分先后地说话,想说多久就说多久,而且每次说话(发送数据帧)的“开场白”非常小。它是一种全双工、有状态的协议。这意味着服务器可以主动向客户端推送数据,而不需要客户端先发起请求,这在实时应用里简直是天赐之物,比如聊天室、在线游戏、股票行情推送等等。HTTP在这种场景下,就得靠轮询或者长轮询来模拟,效率和实时性都差一大截。

在Swoole中,如何实现WebSocket的身份验证和消息广播?

在Swoole里搞WebSocket的身份验证和消息广播,其实是两个比较常见的需求。

先说身份验证。通常,我们会在

onOpen
事件里进行。当一个客户端连接上来,
$request
对象里会包含一些HTTP头信息,比如
Cookie
或者自定义的
Authorization
头。你可以在这里解析这些信息,比如从Cookie里获取Session ID,然后去你的数据库或者缓存里验证这个Session是否有效,或者直接解析JWT令牌。

萤火商城
萤火商城

萤火商城V2.0,是2021年全新推出的一款轻量级、高性能、前后端分离的电商系统,支持微信小程序 + H5+ 公众号 + APP,前后端源码完全开源,看见及所得,完美支持二次开发,可学习可商用,让您快速搭建个性化独立商城。萤火商城V2.0开源版 [uni-app端]如何使用uni-app端一、导入uniapp项目 1. 首先下载HBuilderX并安装,地址:https://www.dcloud

下载
$server->on('open', function (Swoole\WebSocket\Server $server, $request) {
    // 假设客户端在连接时通过查询参数传递了token
    // ws://localhost:9501/?token=YOUR_AUTH_TOKEN
    $token = $request->get['token'] ?? ''; // 或者从 $request->header['cookie'] 中解析
    if (empty($token) || !$this->isValidToken($token)) { // 假设有个isValidToken方法验证
        echo "客户端 {$request->fd} 认证失败,关闭连接。\n";
        $server->disconnect($request->fd); // 直接断开连接
        return;
    }

    // 认证成功,将用户ID和fd关联起来,方便后续查找
    // 比如可以存在一个全局的Map或者Redis里
    $userId = $this->getUserIdFromToken($token); // 假设通过token获取用户ID
    // 假设我们有一个数组来存储fd和userId的映射
    $server->users[$request->fd] = $userId;
    $server->fdToUser[$userId] = $request->fd;

    echo "客户端 {$request->fd} (用户ID: {$userId}) 已连接。\n";
    $server->push($request->fd, "认证成功,欢迎回来!");
});

这里的关键是,一旦认证通过,你需要把

fd
(文件描述符,Swoole给每个连接分配的唯一ID)和你的业务用户ID关联起来,这样在后续需要向特定用户发送消息时,就能通过用户ID找到对应的
fd

接着是消息广播。这个就相对简单了。当你在

onMessage
事件里收到一条消息,想把它发给所有在线用户或者某个特定群组时,你可以遍历所有已建立的连接,然后使用
$server->push()
方法发送。

$server->on('message', function (Swoole\WebSocket\Server $server, $frame) {
    echo "收到客户端 {$frame->fd} 的消息: {$frame->data}\n";

    // 假设是聊天消息,我们要广播给所有在线用户
    foreach ($server->connections as $fd) {
        // 确保连接仍然存在且是WebSocket连接
        if ($server->isEstablished($fd)) {
            $server->push($fd, "用户 {$frame->fd} 说: " . $frame->data);
        }
    }

    // 如果是定向广播给特定群组,你需要维护群组和fd的映射关系
    // 比如:$server->groups['room_A'] = [fd1, fd2, ...];
    // 然后遍历room_A的fd列表进行push
});

Swoole的

$server->connections
属性是一个迭代器,包含了当前所有活跃连接的
fd
。在实际应用中,为了效率和管理方便,你可能不会直接遍历
$server->connections
,而是维护一个你自己的在线用户列表(比如存储在Redis里),这样可以更灵活地进行群发或定向发送。

遇到Swoole WebSocket连接断开或异常,该如何排查?

Swoole WebSocket连接断开或者出现异常,这可是常有的事儿,毕竟网络环境复杂,客户端行为也千奇百怪。排查起来,得有章法。

首先,最直接的线索就是Swoole的日志。Swoole服务器在启动时,可以配置日志文件路径,所有重要的事件、错误都会记录在里面。当连接断开时,

onClose
事件会被触发,但它只告诉你连接断开了,具体原因可能需要结合Swoole自身的错误日志来判断,比如是不是因为某个协程抛了未捕获的异常导致进程崩溃,或者Swoole内部的错误。

其次,要区分是客户端主动断开还是服务器被动断开

  • 客户端主动断开:比如用户关闭了浏览器标签页,或者JS代码里调用了
    ws.close()
    。这种情况下,
    onClose
    会正常触发,通常不会有异常日志。
  • 服务器被动断开:这就有多种情况了。
    1. 心跳超时:WebSocket协议本身没有内置的心跳机制,但为了维持连接活跃和检测死连接,我们通常会实现应用层的心跳。如果客户端长时间没有发送数据,服务器可以发送一个心跳包(ping),客户端收到后回复(pong)。如果服务器在规定时间内没有收到pong,就认为连接已死,会主动断开。Swoole本身没有自动心跳,需要你在
      onWorkerStart
      中设置定时器来发送ping,并在
      onMessage
      中处理pong。
    2. 网络问题:客户端网络波动、服务器网络抖动,都可能导致TCP连接中断,进而WebSocket连接断开。这种情况下,
      onClose
      会触发,但原因可能不明确,需要结合系统日志(如
      dmesg
      )或网络监控工具来判断。
    3. 服务器进程异常退出:Swoole Worker进程因为未捕获的PHP异常、内存溢出等原因崩溃,会导致该Worker上所有连接断开。这时,你应该检查PHP错误日志和Swoole的
      onError
      回调。你可以在
      onError
      里记录更详细的错误信息,帮助定位问题。
    4. 防火墙或代理:中间的网络设备(如防火墙、负载均衡器、CDN)可能会因为配置不当或超时设置,主动关闭空闲连接。确保你的WebSocket连接在这些设备上配置了合适的超时时间,或者通过心跳机制保持活跃。

调试策略:

  • 日志是第一手资料:确保Swoole的日志级别设置得当,并且有足够的磁盘空间来存储。
  • 客户端调试:浏览器的开发者工具(F12)的网络面板可以清楚地看到WebSocket的帧传输,包括发送和接收的数据,以及连接的状态变化,这对于排查客户端行为导致的问题非常有效。
  • 心跳机制:强烈建议为WebSocket连接实现心跳。这不仅能保持连接活跃,还能让你更早地发现死连接,避免资源浪费。一个简单的实现就是服务器每隔N秒发送一个ping帧,客户端收到后立即回复一个pong帧。如果服务器在M秒内没有收到pong,就认为连接已断开并关闭它。
  • 资源监控:监控Swoole进程的CPU、内存使用情况。如果发现异常飙升,可能是代码中存在死循环、内存泄漏等问题。
  • 错误处理:在你的Swoole代码中,对可能抛出异常的地方进行
    try-catch
    ,并在
    onError
    事件中记录详细的上下文信息,这对于定位复杂问题至关重要。

排查这些问题,往往需要耐心和多方面的信息整合。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
swoole为什么能常驻内存
swoole为什么能常驻内存

swoole常驻内存的特性:1. 事件驱动模型减少内存消耗;2. 协程并行执行任务占用更少内存;3. 协程池预分配协程消除创建开销;4. 静态变量保留状态减少内存分配;5. 共享内存跨协程共享数据降低内存开销。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

306

2024.04.10

cookie
cookie

Cookie 是一种在用户计算机上存储小型文本文件的技术,用于在用户与网站进行交互时收集和存储有关用户的信息。当用户访问一个网站时,网站会将一个包含特定信息的 Cookie 文件发送到用户的浏览器,浏览器会将该 Cookie 存储在用户的计算机上。之后,当用户再次访问该网站时,浏览器会向服务器发送 Cookie,服务器可以根据 Cookie 中的信息来识别用户、跟踪用户行为等。

6500

2023.06.30

document.cookie获取不到怎么解决
document.cookie获取不到怎么解决

document.cookie获取不到的解决办法:1、浏览器的隐私设置;2、Same-origin policy;3、HTTPOnly Cookie;4、JavaScript代码错误;5、Cookie不存在或过期等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

368

2023.11.23

阻止所有cookie什么意思
阻止所有cookie什么意思

阻止所有cookie意味着在浏览器中禁止接受和存储网站发送的cookie。阻止所有cookie可能会影响许多网站的使用体验,因为许多网站使用cookie来提供个性化服务、存储用户信息或跟踪用户行为。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

445

2024.02.23

cookie与session的区别
cookie与session的区别

本专题整合了cookie与session的区别和使用方法等相关内容,阅读专题下面的文章了解更详细的内容。

97

2025.08.19

session失效的原因
session失效的原因

session失效的原因有会话超时、会话数量限制、会话完整性检查、服务器重启、浏览器或设备问题等等。详细介绍:1、会话超时:服务器为Session设置了一个默认的超时时间,当用户在一段时间内没有与服务器交互时,Session将自动失效;2、会话数量限制:服务器为每个用户的Session数量设置了一个限制,当用户创建的Session数量超过这个限制时,最新的会覆盖最早的等等。

334

2023.10.17

session失效解决方法
session失效解决方法

session失效通常是由于 session 的生存时间过期或者服务器关闭导致的。其解决办法:1、延长session的生存时间;2、使用持久化存储;3、使用cookie;4、异步更新session;5、使用会话管理中间件。

776

2023.10.18

cookie与session的区别
cookie与session的区别

本专题整合了cookie与session的区别和使用方法等相关内容,阅读专题下面的文章了解更详细的内容。

97

2025.08.19

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

3

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
进程与SOCKET
进程与SOCKET

共6课时 | 0.4万人学习

Redis+MySQL数据库面试教程
Redis+MySQL数据库面试教程

共72课时 | 7.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号