Text协议仅用\n切分消息,不识别\r\n,不处理粘包半包,要求每条消息必须以\n结尾,否则会阻塞;input()函数扫描首个\n位置返回偏移量,未找到则返回0等待更多数据。

Text协议就是用\n切数据,不是\r\n
Workerman 的 TextProtocol 本质就是按行读取:每次收到数据后,遇到第一个 \n 就截断,把前面部分当作一条完整消息。它不识别 \r\n,也不处理粘包或半包的边界逻辑——这些都交给底层 TCP 流自己“凑齐”,协议只负责切。
常见错误现象:
– 客户端发 "hello\r\n",服务端收不到完整消息,甚至卡住
– 多条消息合并成一个 TCP 包(如 "a\nb\nc\n"),TextProtocol 会正确拆成三条,但若中间缺 \n(如 "a\nb"),第二条就一直等下去
- 必须确保每条消息末尾是
\n,不能是\r\n或\r - 发送方如果是 Windows 环境下的 Python、Node.js 等,默认可能用
\r\n,得显式改成\n - 如果消息本身含
\n(比如 JSON 多行字符串),TextProtocol会误切——它不适合传结构化/可变长内容
TextProtocol 的 input() 函数怎么判断一条消息结束
input() 是 Workerman 协议解析入口函数,返回值决定是否凑够一条消息。对 TextProtocol 来说,它的实现极简:扫描输入缓冲区,找到第一个 \n 的位置,返回该偏移量;没找到就返回 0,表示继续等数据。
使用场景:
– 你自定义协议时参考这个逻辑,别直接复制——比如想支持 \r\n,就得改扫描条件
– 调试时可在 input() 里加日志,看实际传入的 $buffer 是什么内容
- 返回值是整数:>0 表示切掉前 N 字节作为消息;0 表示暂不处理;-1 表示丢弃整个缓冲区(极少用)
- 它不修改原
$buffer,只是告诉 Workerman “从开头截多少” - 如果缓冲区里有多个
\n,input()只认第一个——剩下的留给下一次调用处理
为什么不用 TextProtocol 处理 JSON 或二进制数据
因为 TextProtocol 的切分逻辑和数据语义完全脱钩。它不管内容是不是合法 JSON,也不管字节是不是 UTF-8 编码,只机械找 \n。一旦消息体里自带换行(比如缩进 JSON、日志多行堆栈),就会被提前截断。
性能影响:
– 看似简单,但频繁扫描缓冲区 + 多次内存拷贝(每次切一条就 new 一个字符串),在高并发小消息场景下比固定包头协议更耗 CPU
– 没有长度校验,无法防御恶意超长行攻击(比如发一个 1GB 的无 \n 字符串,缓冲区会不断增长)
- JSON 推荐用
JsonProtocol(需两端约定格式)或自定义协议 +pack/unpack - 二进制协议必须绕过
TextProtocol,改用FrameProtocol或手写input()解析包头长度 - 哪怕只是传纯文本日志,也建议加长度前缀,避免单行日志意外含
\n
Workerman 启动时提示 Unknown protocol: Text 怎么办
这不是协议名写错,而是类没加载。Workerman 5.x 开始默认不自动注册 TextProtocol,必须手动 use 并传类名字符串,或者传完整类路径。
典型错误:
– 写 'protocol' => 'Text' → 报错
– 写 'protocol' => \Workerman\Protocols\TextProtocol::class → 正确
- 确认 Workerman 版本 ≥ 4.0.0(旧版类路径不同,可能是
Workerman\Protocols\Text) - 如果用 Composer 自动加载,确保没有拼错命名空间,IDE 可能提示补全但实际类不存在
- 命令行启动时加
-d参数开启 debug,能看到协议类是否成功实例化
\r\n),就得立刻换协议。










