Workerman 5.2.3 自定义协议调试需分层验证:先确保 input 准确返回包长(>0)、等待(0)或断连(false),再检查 decode 是否正确还原结构,最后确认 encode 输出与 input 解析严格对称,配合协程适配日志和手动十六进制测试。

调试 Workerman 5.2.3 的自定义协议通信,关键在于分层定位:先确认数据是否完整到达(input 层),再检查解包是否正确(decode),最后验证封包与发送是否合规(encode)。不能只依赖 var_dump 或日志打印,必须结合协议逻辑和缓冲区状态来判断。
确认 input 方法是否准确识别包边界
这是粘包/拆包问题的第一道关卡。如果 input 返回错误长度或始终返回 0,后续所有逻辑都不会触发。
- 在
input方法开头加日志,打印当前$buffer的十六进制和长度:file_put_contents('/tmp/input.log', bin2hex($buffer).'('.strlen($buffer).")\n", FILE_APPEND); - 确保返回值严格为整数:完整包长度(>0)、等待更多数据(0)或关闭连接(false)。返回
null或字符串会导致 Workerman 静默忽略 - 典型错误:协议约定前 4 字节是包长(network byte order),但用
unpack('L', $buffer)读取时未截取前 4 字节,或未处理字节序转换(应使用unpack('N', $header)[1])
验证 decode 是否还原出预期结构
Workerman 只有在 input 返回有效长度后,才会把对应字节传给 decode。这里出错常表现为 onMessage 收到空、乱码或 null。
- 在
decode中先校验输入长度:if (strlen($buffer) ,避免解包崩溃 - 若协议含 JSON 内容,解包后立即
json_last_error()检查;若含二进制字段,用hex2bin或unpack后用is_array判断结果类型 - 不要直接返回原始
$buffer,而应返回明确结构,例如:return ['type' => $type, 'data' => $payload];,方便onMessage安全消费
检查 encode 是否生成合法可解析的字节流
encode 的输出会原样发给客户端,若格式不匹配客户端预期,对方将无法解包——这常被误判为服务端问题,实则是双向协议不一致。
- 在
encode返回前记录原始输出:file_put_contents('/tmp/encode.log', bin2hex($packed).'('.strlen($packed).")\n", FILE_APPEND); - 确保打包结果与
input的解析逻辑严格对称:比如input用N读包头,encode就必须用pack('N', $len)写包头 - 测试时可用
telnet或nc手动发送十六进制数据(如printf '\x00\x00\x00\x0b{"a":1}' | nc 127.0.0.1 8000),绕过客户端,直验服务端协议层
启用 Workerman 5.2.3 协程环境下的调试支持
5.2.3 默认运行在协程模式,传统阻塞式调试(如 sleep + var_dump)可能干扰事件循环,需适配。
- 禁用守护模式启动:
php start.php start,确保控制台实时输出 - 开启框架级调试:
\Workerman\Config::$debug = true;(放在 Worker 实例化前),可看到协议类加载、连接建立、分包触发等内部事件 - 使用
Worker::log()替代echo,它自动添加时间戳和进程 ID,多进程下日志不混淆 - 若怀疑协程调度异常,临时关闭协程:
Worker::$useGlobalEventLoop = false;,回退到传统 Reactor 模式对比验证

















