php websocket客户端发送中文失败主因是字符串非utf-8编码;需确保源字符串为utf-8,gbk等需用mb_convert_encoding转换;utf8_encode仅适用于iso-8859-1;握手阶段不支持charset;帧格式错误(如bom、未掩码、json转义)也会导致失败。

PHP 客户端连接 WebSocket 时无法发送中文?编码问题出在哪儿
PHP 本身没有原生 WebSocket 客户端,你用的大概率是 ext-websocket(已废弃)、ratchet/pawl、textalk/websocket 或手写 socket。这些库都不处理应用层字符编码——WebSocket 协议强制要求 payload 必须是 UTF-8 编码的字节流,PHP 脚本里传进去的字符串如果不是 UTF-8,就会乱码或触发协议错误。
用 textalk/websocket 发送中文前必须 utf8_encode() 吗
不一定,取决于你的源字符串编码。PHP 的 mb_internal_encoding() 和文件保存编码只是影响 PHP 内部函数行为,不改变实际字节。关键看变量值本身:
- 如果字符串来自 UTF-8 编码的 PHP 文件(推荐),且没被
iconv()或mb_convert_encoding()污染过,直接传入即可 - 如果来自 GBK 数据库、GBK 表单 POST 或旧系统接口,必须先转成 UTF-8:
mb_convert_encoding($str, 'UTF-8', 'GBK') -
utf8_encode()只适用于 ISO-8859-1 字符串,对 GBK/GB2312 会错乱,别乱用
WebSocket 握手阶段要不要设 charset
不用,也不能设。Sec-WebSocket-Accept 和 Upgrade 头部不支持 charset 参数。HTTP 握手请求头里加 Content-Type: application/json; charset=utf-8 是无效的——WebSocket 协议规范明确禁止在握手阶段传输 body,所有参数都在 headers 里,而 headers 值必须是 ASCII 字符。真正要管的是你后续 send() 的数据体。
服务端收不到中文或报 “invalid frame header” 怎么查
这类错误往往不是编码问题,而是帧格式破坏。常见原因:
立即学习“PHP免费学习笔记(深入)”;
- PHP 字符串里混入了不可见控制字符(比如 Windows 换行
\r\n或 BOM),用bindec(decbin(ord($s[0])))检查首字节是否为 0xEF(UTF-8 BOM 开头) - 用
fsockopen()手写 WebSocket 时,没正确实现掩码(mask)字段:客户端发帧必须 mask=1,且 mask key 要参与 payload 异或,否则服务端直接断连 - 用了
json_encode()但没加JSON_UNESCAPED_UNICODE,导致中文被转成\u4f60\u597d,虽然合法但增大体积,某些弱实现服务端解析失败
最稳妥的做法:发送前用 mb_check_encoding($data, 'UTF-8') 校验,再用 json_encode($data, JSON_UNESCAPED_UNICODE | JSON_INVALID_UTF8_SUBSTITUTE) 处理数组结构。











