不是必须,但绝大多数自定义场景下input和encode缺一不可;input用于判断数据包完整性以解决粘包,encode用于序列化返回值确保客户端可解析。
Workerman 自定义协议必须实现
和
吗?
不是必须,但绝大多数自定义场景下,这两个方法缺一不可。Workerman 的协议解析流程是:收到原始数据 → 调用
判断是否收齐一帧 → 收齐后调用
(如果存在)→ 处理业务逻辑 → 返回值交给
序列化发送。如果你跳过
,TCP 粘包问题会直接导致
收到半包或乱包;不实现
,返回值会被强制转成字符串(比如数组变
),客户端根本没法解析。
方法怎么写才不丢包、不卡死?
的唯一职责是:告诉 Workerman “当前缓冲区里有没有一个完整的数据单元”。它不能做解析,不能修改缓冲区,不能抛异常,返回值只能是
(没收到完整包)、正整数(包长度)、
(连接应关闭)。常见错误是返回负数或非数字,会导致 Worker 进程静默退出。
定长协议:直接返回固定长度,比如
带包头的变长协议(如前 4 字节是 body 长度):先检查缓冲区是否 ≥ 4,再读出长度
,最后判断
,满足则返回
,否则返回
行协议(如 HTTP、Redis):用
找分隔符,找到就返回位置 + 2,找不到返回
绝对不要在
里调用
或
截取数据——这是
的事
方法和
怎么配对才不出错?
的输入是
的返回值(或
的参数),输出必须是
;
的输入是
切出来的完整包,输出应该是业务能直接用的结构(如数组、对象)。两者类型要严格镜像:如果
返回
,那
就该接受同样结构并吐出二进制或 JSON 字符串。
JSON 协议:decode 用
,encode 用
二进制协议:decode 用
拆字段,encode 用
组包,注意字节序(
大端,
小端)和字段顺序必须完全一致
别在
里加换行或空格——除非协议明确要求,否则容易被客户端当成脏数据
如果
返回非 string(比如 null、array),Workerman 会静默转成空字符串,对方收不到任何东西
Workerman 7+ 的协议类写法和老版本有啥关键差异?
Workerman 7 开始强制要求协议类继承
,且
和
必须声明为 public,签名也变了:
、
。老版本允许返回
表示断连,新版本得抛
。
旧写法
在 v7+ 会触发致命错误
新协议类里,
不再是可选方法,如果没定义,Workerman 会把原始 buffer 当作字符串传给
路径上,v7+ 的协议类建议放在
,自动加载更稳定,别再扔在
里硬改
调试时看
,重点搜
或
这类提示
实际跑起来最常出问题的地方,是
返回了不确定值(比如有时 0,有时 false),或者
对 null 值没做兜底。这些不会报错,但会让连接看起来“时好时坏”,查起来特别费时间。
inputencodeinputdecodeencodeinputonMessageencodeArrayinputinput0falsereturn 16;$len = unpack('N', $buffer)[1]strlen($buffer) >= 4 + $len4 + $len0strpos($buffer, "\r\n")0inputsubstrmb_substrdecodeencodedecodeencodeonMessagesend()stringdecodeinputdecode['cmd' => 'login', 'data' => [...]]encodejson_decode($buffer, true)json_encode($data, JSON_UNESCAPED_UNICODE)unpackpackNVencodeencodeWorkerman\Protocols\ProtocolInterfaceinputencodeinput(string $buffer): ?intencode(mixed $data): stringfalseWorkerman\Connection\ConnectionExceptionpublic function input($buffer) { return false; }decodeonMessageapp/Protocols/YourProtocol.phpvendorWorker::$logFileProtocol input returned invalidencode must return stringinputencode