coroutineclient与client是两套独立实现,前者需协程环境运行,混用会导致阻塞;其set()影响connect/send/recv全阶段,connect失败须显式close(),且原生函数仍阻塞,需runtime::enablecoroutine启用全局协程钩子。

不是继承关系,也不是简单“协程版替换”,而是两套完全独立的实现:Client是同步阻塞式,CoroutineClient是原生协程调度式,混用会直接卡死进程。
CoroutineClient 不能在同步回调里直接调用
常见错误现象:Co::getcid() 返回 0,$client->connect() 阻塞整个 worker,CPU 占满但无响应。
原因:Swoole 的 onReceive、onMessage 等回调默认不运行在协程中(除非 enable_coroutine => true);此时调用 CoroutineClient 会因缺少协程上下文而退化为同步阻塞。
- 检查当前是否在协程环境:
var_dump(Co::getcid() > 0) - 若为
false,必须用go()或Co un()包裹客户端逻辑 - PHP-FPM 或 CLI 普通脚本中,
CoroutineClient必须配合Co un()启动协程调度器
Client 的 set() 和 CoroutineClient 的 set() 行为不一致
虽然接口签名相同,但底层作用对象不同:
Swoole 6.1.1 是一个专为 PHP 设计的高性能事件驱动并发网络引擎。作为稳定版,它修复了编译时对 zlib 依赖的缺失及 curl 模块的内存安全风险。该版本支持协程、多线程与多进程架构,内置 TCP/HTTP/WebSocket 服务器,能够显著提升 PHP 在微服务、实时通信等场景下的执行效率与并发能力。
-
Client->set(['timeout' => 3]):只影响后续connect(),send()和recv()仍用系统默认超时 -
CoroutineClient->set(['timeout' => 3]):同时作用于connect()、send()、recv()三个阶段(文档明确说明“connect超时设置同时作用于Connect、Recv和Send超时”) -
open_length_check等协议配置项两者都支持,但CoroutineClient在协程调度下能更稳定处理粘包/半包
connect() 失败后不 close() 就重试会触发 Errno 9
错误现象:$client->errCode 返回 9(EBADF),而不是预期的 110(ETIMEDOUT)。
原因:CoroutineClient 内部 socket fd 在 connect 失败后未自动释放,残留无效句柄;再次调用 connect() 会尝试复用已损坏的 fd。
- 必须显式调用
$client->close()清理资源,再 new 一个新实例或重新connect() - 不要依赖
isConnected()判断连接状态——它只反映上一次操作后的 socket 句柄有效性,不保证网络可达 - 超时后
$client->recv()返回false,此时$client->errCode是SOCKET_ETIMEDOUT(常为 110),但 socket 仍处于打开状态,需按业务决定是否close()
最易被忽略的一点:即使开了 enable_coroutine => true,file_get_contents()、curl_exec() 这类原生函数依然阻塞——CoroutineClient 的非阻塞能力只对自身 API 生效,不自动传染到 PHP 全局函数。真要混用,得提前调用 SwooleRuntime::enableCoroutine(SWOOLE_HOOK_ALL),否则协程就只是个“看起来像异步”的假象。










