Workerman客户端连第三方WebSocket API必须用AsyncTcpConnection或workerman/websocket-client,因WebSocketConnection仅支持服务端接收;需手动实现握手与帧编解码,或直接使用封装好的客户端库。

Workerman WebSocket客户端连第三方API,别用 WebSocketConnection
Workerman 自带的 WebSocketConnection 只能用于服务端接收浏览器连接,不能主动发起 WebSocket 连接——想连第三方 API(比如行情推送、聊天网关),必须用 AsyncTcpConnection 手动实现 WebSocket 握手和帧解析。
常见错误现象:Connection refused 或握手后立刻断开,其实是误把 WebSocketConnection 当客户端用,或者没发 Upgrade 请求头。
- 必须用
AsyncTcpConnection实例,协议前缀写ws://或wss://(底层会自动处理 TLS) - 连接建立后,要手动发送标准 WebSocket 握手请求(含
Upgrade: websocket、Sec-WebSocket-Key等头) - 收到 101 响应后,才算握手成功;之后收发数据需按 WebSocket 帧格式(RFC 6455)打包/解包
-
workerman/websocket-client是个轻量封装,推荐直接装它,避免重复造轮子
用 workerman/websocket-client 发起连接最稳
这个包本质就是基于 AsyncTcpConnection 封装了握手、ping/pong、帧编解码,兼容 wss、支持自定义 header 和超时,比手撸可靠得多。
使用场景:对接币安 WebSocket 行情、Pusher、自建 WebSocket 网关等需要主动连接的服务。
- 安装:
composer require workerman/websocket-client - 连接示例中,
$client->onConnect触发时握手已完成,可直接$client->send() - 注意
onMessage回调里收到的是解包后的原始 payload(string 或 binary),不是原始帧 - 若第三方要求带 token 或 cookie,通过
new WebSocket('url', ['headers' => [...]])传入
$client = new WebSocket('wss://stream.binance.com:9443/ws/btcusdt@ticker');
$client->onConnect = function($client) {
echo "Connected\n";
};
$client->onMessage = function($client, $data) {
$json = json_decode($data, true);
echo $json['c'] ?? 'no price';
};
$client->onError = function($client, $code, $msg) {
echo "Error: $code $msg\n";
};
AsyncTcpConnection 手动握手的三个关键点
不依赖第三方包时,得自己处理握手细节。容易被忽略的坑全在这三步里:
-
Sec-WebSocket-Key必须是 base64 编码的 16 字节随机值(不能硬编码,也不能用时间戳生成) - 握手响应必须严格匹配
HTTP/1.1 101 Switching Protocols,且含Sec-WebSocket-Accept头;少一个字段或大小写错都会失败 - 握手成功后,第一次发数据前,必须先发一个 ping 帧(opcode 0x9)或等待对方 ping——有些服务端会因无心跳直接断连
性能影响:手写握手逻辑调试成本高,但内存占用略低;用 websocket-client 多一层封装,对长连接吞吐影响可忽略。
WSS 连接失败常见原因和验证方式
不是证书问题,大概率是 DNS、代理或 TLS 版本不匹配。Workerman 默认用系统 OpenSSL,不支持老旧 TLS 1.0。
- 先用
openssl s_client -connect stream.binance.com:9443 -servername stream.binance.com测试基础 TLS 握手是否通 - 如果报
sslv3 alert handshake failure,说明服务端要求 TLS 1.2+,而 PHP OpenSSL 版本太低(需 ≥ 1.0.2) - 公司内网环境常拦截 wss 升级请求,可临时改用
tcp://+ 手动加 SSL 层(不推荐,绕过证书校验风险高) - 用
tcpdump抓包看是否发出 Upgrade 请求——没发,说明AsyncTcpConnection还没走到 send 阶段
真正麻烦的从来不是连上,而是连上后对方协议私有、没文档、ping timeout 设置不一致,这些得靠抓包和反复试错。

















