Workerman 4.0.10 中文乱码根源在于编码链路断裂:终端默认GBK(CP936)与UTF-8源码不匹配、PHP未声明default_charset、文件含BOM导致静默退出、HTTP响应头缺失charset声明、HTML仅靠meta无HTTP头保障、WebSocket误用iconv二次转码;需依次执行chcp 65001、ini_set('default_charset', 'UTF-8')、保存为UTF-8无BOM、设置Content-Type头含charset=utf-8、HTML双重声明、禁用非必要编码转换。

Workerman 4.0.10 启动后命令行输出中文变成或方块,HTTP响应返回的JSON里中文字段显示为乱码,浏览器渲染HTML时文字错位——这不是字体问题,而是编码链路中某处默认使用了GBK或ISO-8859-1,而你的源码、终端、HTTP头全部按UTF-8约定编写,却在关键环节被悄悄覆盖。
cmd/PowerShell终端启动时中文显示为
Windows默认终端编码是GBK(CP936),而PHP文件保存为UTF-8,php.exe读取源码时按系统默认编码解析,导致字符串字面量解码失败。
第一步:打开cmd或PowerShell,执行chcp 65001切换当前会话为UTF-8编码。
第二步:在Workerman启动脚本顶部添加强制声明:ini_set('default_charset', 'UTF-8');,防止PHP内部字符函数默认走latin1。
第三步:确保你的start.php文件本身以UTF-8无BOM格式保存——用VS Code右下角点击编码→“Save with Encoding”→选UTF-8;若用记事本另存为,必须取消勾选“UTF-8签名(BOM)”,否则Workerman加载时会报Parse error。
这一步操作起来很简单,直接把文件拖进去就行。但【一旦文件含BOM,Worker::runAll()会静默退出,不报任何错误】,只在终端闪退,极易误判为端口占用或权限问题。
HTTP响应中JSON中文变问号或\ud83d\ude00
浏览器收到JSON但中文显示为Unicode转义或方框,说明响应体是UTF-8编码,但HTTP响应头缺失charset声明,浏览器按ISO-8859-1解析。
方法一:手动设置Content-Type头
在onMessage回调中,发送前必须显式写入响应头:
$connection->header('Content-Type', 'application/json; charset=utf-8');
$connection->send(json_encode(['msg' => '你好'], JSON_UNESCAPED_UNICODE));
注意:不能只写application/json,缺了; charset=utf-8,Chrome/Firefox会降级为Latin1解码。
方法二:封装响应函数避免遗漏
定义一个复用函数:
function sendJson($connection, $data) { $connection->header('Content-Type', 'application/json; charset=utf-8'); $connection->send(json_encode($data, JSON_UNESCAPED_UNICODE));}
后续所有JSON响应统一调用sendJson($connection, [...]),从源头杜绝漏设头。
HTML页面中文渲染异常
访问http://127.0.0.1:2345看到HTML页面标题或正文全是方块,检查发现HTML源码里中文正常,但浏览器没按UTF-8解析。
必须在HTTP响应头中声明charset,并在HTML内嵌meta双重保障:
$connection->header('Content-Type', 'text/html; charset=utf-8');
$connection->send('<!DOCTYPE html><html><head><meta charset="UTF-8"></head><body>你好</body></html>');
仅靠<meta charset="UTF-8">不够——当HTTP头未声明时,浏览器可能延迟解析meta,先按错误编码渲染再重绘,造成闪烁或残留乱码。
另外,【若HTML中混用中文与全角标点(如,。!),且未声明UTF-8,IE会直接崩溃白屏】,现代浏览器虽兼容性好,但仍建议严格保持头与meta一致。
WebSocket连接后接收中文消息乱码
客户端发来UTF-8中文,服务端$data打印出来是,说明TCP层收包正确,但PHP字符串处理时被二次转码。
Workerman WebSocket协议默认不做字符编码转换,$data就是原始字节流。若你用iconv('GBK', 'UTF-8', $data)强行转换,反而会把本来正确的UTF-8字节当GBK解,越转越乱。
正确做法:确认客户端发送时用的是UTF-8编码(如JavaScript中ws.send(JSON.stringify({text: "你好"}))天然UTF-8),服务端直接使用,不做任何iconv或mb_convert_encoding干预。
调试时可用bin2hex($data)验证:正常UTF-8中文“你好”对应e4bda0e5a5bd,若看到b0a1c3a5之类,则是客户端发错了编码,需前端修复。

















