unknown protocol错误源于workerman协议校验失败:收到数据既非http也非注册协议格式,常见于http客户端连tcp服务或tcp客户端发非预期数据;自定义协议中input()返回null、非数组或非false即触发。

Workerman抛出“Unknown protocol”错误的直接原因
这个异常不是PHP报的,而是Workerman内部在onMessage回调前做的协议校验失败导致的——它发现收到的数据既不符合HTTP格式,也不符合你注册的自定义协议解析规则,于是直接丢弃连接并抛出Unknown protocol。常见于用HTTP客户端(如curl)连了纯TCP服务,或TCP客户端发了非预期格式的二进制数据。
如何确认是不是协议不匹配
先看服务端启动时指定的协议类是否和客户端行为一致:
- 如果用了
new Worker('tcp://0.0.0.0:2345'),那客户端必须走裸TCP,不能发HTTP请求(比如带GET / HTTP/1.1头) - 如果用了
new Worker('http://0.0.0.0:2345'),客户端必须发标准HTTP请求,不能只发一串JSON字节流 - 如果用了自定义协议(如继承
Workerman\Protocols\ProtocolInterface),必须确保input()方法能识别首字节、包头长度等关键特征,否则会直接判为未知
自定义协议里input()返回null就触发该异常
Workerman要求input()方法返回一个完整消息数组(如['type' => 1, 'body' => $data])或false(表示还需等待更多数据)。一旦返回null或非数组/非false值,框架就认为协议无法识别,立刻中断连接。
典型踩坑点:
- 包头长度字段读取错误(比如用
unpack('n', $buf)读4字节长度却只传了2字节)→ 解包失败返回false以外的值 - 没处理TCP粘包,
input()里直接substr($buffer, 0, $len)但$len超出当前$buffer长度 → 返回false本意是“等数据”,但逻辑写错返回了null - 协议状态机未重置,第二次调用
input()时仍处于STATE_WAIT_BODY但缓冲区已空 → 忘记返回false,默认返回null
调试时最容易被忽略的一点
Unknown protocol异常本身不带堆栈,也不会进set_exception_handler——它是在Workerman底层解析循环里硬判断的,所以日志里看不到详细上下文。真要定位,得在自定义协议类的input()开头加var_dump(strlen($data), bin2hex($data)); die;,看第一段原始字节到底长什么样、有没有你协议约定的魔数或固定头。











