乱码非协议问题,而是UTF-8字节流被错误解码;JS发送前需检查页面编码、接口响应头及JSON转义,PHP应确认源编码后转UTF-8并校验,Python须显式指定文件/输入编码,Java需URL编码查询参数,全链路须统一UTF-8。

乱码不是 WebSocket 协议的问题,而是 UTF-8 字节流在某处被当成别的编码解了——协议本身不协商 charset,只强制要求文本帧 payload 必须是合法 UTF-8 字节序列。
WebSocket send() 传字符串却显示乱码?先检查 JS 字符串源头
浏览器调用 ws.send("你好") 时,JS 引擎会自动把 UTF-16 字符串转成 UTF-8 字节再发。但乱码往往发生在“发送前”:
- 页面
<meta charset="gbk">声明错误,导致input.value读出来就是损坏的字符串 - 字符串来自
fetch()或 JSON 接口,但响应头没设Content-Type: application/json; charset=utf-8,部分旧浏览器可能用系统默认编码解析 - 用了
JSON.stringify({msg: "你好"})却漏了JSON_UNESCAPED_UNICODE,结果发的是{"msg":"\u4f60\u597d"}——虽合法,但某些弱实现服务端会拒收或错解 - 更稳妥的做法:用
TextEncoder显式控制字节流:ws.send(new TextEncoder().encode("你好")),彻底绕过隐式转换
PHP 客户端发中文前必须用 utf8_encode() 吗?别乱用
utf8_encode() 只接受 ISO-8859-1 输入,对 GBK/GB2312 字符串直接错乱。真正该做的是:
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
- 确认源字符串真实编码:来自数据库?表单 POST?用
mb_detect_encoding($str)粗略判断(别依赖它) - 统一转 UTF-8:
mb_convert_encoding($str, 'UTF-8', 'GBK')(适用于 GBK 源),或iconv('GB2312', 'UTF-8//IGNORE', $str) - 发送前校验:
mb_check_encoding($str, 'UTF-8')返回 false 就别发,否则服务端大概率断连 - 若用
json_encode()包装数据,务必加JSON_UNESCAPED_UNICODE标志
Python websocket-client 收到中文是 bytes 类型?别急着 decode
ws.recv() 返回的是 Python str(Unicode),直接用即可;只有 ws.recv_data() 才返回 bytes。常见误操作:
- 从文件读取:
open('config.json').read()必须显式指定encoding='utf-8',否则 Windows 下默认用 cp936 - 终端输入:
input()在 Windows 上返回的是 GBK 编码的str,需先text.encode('gbk').decode('utf-8')(仅当确定源是 GBK) - 收到
bytes时,先剥离 BOM:data.lstrip(b'\xef\xbb\xbf').decode('utf-8')
Java @OnMessage 方法里中文变 “???”?查 URL 查询参数解码
WebSocket 握手阶段没有 charset 可设,Sec-WebSocket-Accept 和 Upgrade 头部也不支持 charset 参数。问题常出在连接 URL 的 query string 里传中文,比如:ws://host/path?name=张三:
- Tomcat/Jetty 默认用 ISO-8859-1 解析 query string,导致中文变 “???”
- 不要依赖容器自动 decode;应在服务端手动用
URLDecoder.decode(queryString, "UTF-8") - 更安全的做法:客户端发连接 URL 前先
encodeURIComponent("张三"),服务端再URLDecoder.decode(..., "UTF-8")
最容易被忽略的是多帧 TCP 包:客户端高频发送时,多个 WebSocket 帧可能被合并进一个 TCP 包。服务端若只解析第一个帧,后续帧头部会被当 payload 解,直接错乱。抓包看原始十六进制最可靠——如果服务端收到的是 EF BB BF E4 BD A0(标准 UTF-8),但解出来是乱码,说明解码端用了 GBK;如果收到的是 C4 E3 C0 D2(GBK 字节),那问题出在发送端没转 UTF-8。

















