Workerman如何实现物联网(IoT)设备硬件TCP双向通信?

雨强同学_9139

雨强同学_9139

2026-05-25

607人浏览

原创

workerman 适合作为 iot tcp 双向通信底座,但需手动处理连接生命周期、协议解析(如粘包)、设备身份绑定及跨服务转发;建议在 onconnect 中握手并绑定设备 id,设置心跳,缓存并按协议头切分数据,通过映射表实现 websocket 精准控制硬件。

workerman如何实现物联网(iot)设备硬件tcp双向通信?

Workerman 本身不封装硬件通信逻辑,但它是极适合做 IoT TCP 双向通信底座的 PHP 框架——关键在于你得自己处理连接生命周期、协议解析和跨服务转发,不能指望开箱即用。


为什么不能直接用 Worker 类监听硬件端口就完事?

  • 硬件设备(如温湿度传感器、PLC)通常以固定格式发包(比如 Modbus TCP 帧、自定义二进制头+JSON 负载),Worker 的 onMessage 回调只收到原始字节流,不做解析就无法识别指令或状态
  • onMessage 触发时,$connection 是单次 TCP 连接对象,但硬件可能长连不发心跳,容易被误判为“空闲断开”
  • 默认没有连接池、无设备身份绑定机制,多个设备连上来后,WebSocket 端或 HTTP API 想定向推送给某台设备,根本找不到对应 $connection

常见错误现象:

  • 设备连上后发几条数据就断,日志里没报错 → 实际是 $connection->close() 被隐式触发(比如未设置 $connection->protocol 或未处理粘包)
  • 同一 IP 多个设备复用连接,后连的把前连的踢掉 → Worker 默认按 IP+port 去重,需手动用设备 ID 替换 key

建议做法:

  • 在 onConnect 中立刻发送握手响应,并要求设备回传唯一标识(如 MAC、SN)
  • 把设备 ID 作为键存入全局数组:$websocket->deviceConnections[$deviceId] = $connection
  • 设置 $connection->heartbeatIdle = 60 和 $connection->heartbeatData = 'ping' 防止被中间设备断连

onMessage 里怎么安全解析硬件 TCP 数据?

硬件协议几乎都存在粘包、半包问题,不能直接 json_decode($data)。必须先按协议头长度字段切分。

以常见「4 字节长度 + JSON 内容」格式为例:

  • 先缓存未完整帧:$connection->tmpBuffer .= $data
  • 循环检查是否有完整包:若 strlen($connection->tmpBuffer) >= 4,读前 4 字节得 $len = unpack('N', $connection->tmpBuffer)[1]
  • 若 strlen($connection->tmpBuffer) >= 4 + $len,则截取 substr($connection->tmpBuffer, 4, $len) 解析,再更新 $connection->tmpBuffer

要点:

  • 不要用 explode 或 strpos 找分隔符,硬件不会给你发 \n\r
  • 解析失败时别 close(),记录日志并丢弃当前缓冲区,否则设备重连风暴
  • 如果协议含 CRC 校验,必须在切包后立即验证,不通过直接跳过

如何让 WebSocket 页面实时控制某台硬件设备?

不能靠「广播给所有 TCP 连接」,得精准路由。最简方案是:在 WebSocket 服务端维护一个映射表,设备上线时注册,下线时注销。

示例结构:

Mark Copy
Mark Copy

Mark Copy是一款AI文本写作工具,SEO 写作与营销文案工具。

下载
$websocket->deviceMap = [
    'SN-88A2F1' => ['conn' => $tcpConn, 'ip' => '192.168.2.105'],
    'SN-B3C9E7' => ['conn' => $tcpConn, 'ip' => '192.168.2.106']
];

当 WebSocket 收到控制指令(如 {"cmd": "relay_on", "device": "SN-88A2F1"}):

  • 先查 $websocket->deviceMap[$device] 是否存在且 $conn->isConnected() 为 true
  • 再调用 $conn->send($payload),注意 payload 必须是硬件能识别的二进制或文本协议格式
  • 若设备离线,返回 {"status": "offline", "device": "SN-88A2F1"} 给前端,别静默失败

容易踩的坑:

  • 忘记判断 $conn->isConnected(),对已断开连接调 send() 会触发 warning 并卡住事件循环
  • WebSocket 消息里设备 ID 写错大小写或带空格,查不到映射 → 建议入库前统一 trim(strtolower())
  • 没加超时控制,硬件响应慢导致整个 onMessage 阻塞 → 复杂指令应投递到 TaskWorker 异步处理

要不要用 GatewayWorker 或 think-worker?

如果你的硬件数量超过 50 台,或需要对接 TP 业务系统(比如设备状态存数据库、触发订单流程),直接上 GatewayWorker 更省事。

它天然提供:

  • BusinessWorker 专门处理业务逻辑,与 Gateway 解耦
  • registerAddress 自动管理设备连接归属,不用手写映射表
  • 内置 Gateway::sendToUid(),只要给设备分配 uid(如 SN-88A2F1),就能直接推送

但代价是:

  • 多一层进程模型,调试时要分清是 Gateway 进程还是 BusinessWorker 进程出问题
  • onMessage 回调里拿不到原始 $connection,只能通过 Gateway::getClientIdByUid() 间接操作,灵活性略降

如果只是小项目(Worker + 手动管理连接更轻量,也更容易定位粘包或协议解析问题。

真正难的从来不是启动几个 Worker,而是设备上线那一刻,你有没有在 3 秒内确认它发的是什么、想干什么、该回什么。

相关专题

更多
php文件怎么打开
php文件怎么打开

打开php文件步骤:1、选择文本编辑器;2、在选择的文本编辑器中,创建一个新的文件,并将其保存为.php文件;3、在创建的PHP文件中,编写PHP代码;4、要在本地计算机上运行PHP文件,需要设置一个服务器环境;5、安装服务器环境后,需要将PHP文件放入服务器目录中;6、一旦将PHP文件放入服务器目录中,就可以通过浏览器来运行它。

2023.09.01

10344

6

php怎么取出数组的前几个元素
php怎么取出数组的前几个元素

取出php数组的前几个元素的方法有使用array_slice()函数、使用array_splice()函数、使用循环遍历、使用array_slice()函数和array_values()函数等。本专题为大家提供php数组相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.11

6081

5

php反序列化失败怎么办
php反序列化失败怎么办

php反序列化失败的解决办法检查序列化数据。检查类定义、检查错误日志、更新PHP版本和应用安全措施等。本专题为大家提供php反序列化相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.11

2115

5

php怎么连接mssql数据库
php怎么连接mssql数据库

连接方法:1、通过mssql_系列函数;2、通过sqlsrv_系列函数;3、通过odbc方式连接;4、通过PDO方式;5、通过COM方式连接。想了解php怎么连接mssql数据库的详细内容,可以访问下面的文章。

2023.10.23

3828

4

php连接mssql数据库的方法
php连接mssql数据库的方法

php连接mssql数据库的方法有使用PHP的MSSQL扩展、使用PDO等。想了解更多php连接mssql数据库相关内容,可以阅读本专题下面的文章。

2023.10.23

4534

6

html怎么上传
html怎么上传

html通过使用HTML表单、JavaScript和PHP上传。更多关于html的问题详细请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.03

3551

9

PHP出现乱码怎么解决
PHP出现乱码怎么解决

PHP出现乱码可以通过修改PHP文件头部的字符编码设置、检查PHP文件的编码格式、检查数据库连接设置和检查HTML页面的字符编码设置来解决。更多关于php乱码的问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.09

5077

8

php文件怎么在手机上打开
php文件怎么在手机上打开

php文件在手机上打开需要在手机上搭建一个能够运行php的服务器环境,并将php文件上传到服务器上。再在手机上的浏览器中输入服务器的IP地址或域名,加上php文件的路径,即可打开php文件并查看其内容。更多关于php相关问题,详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2023.11.13

3982

8

sprintf函数用法详解
sprintf函数用法详解

sprintf函数的用法:1、格式化字符串;2、指定输出宽度和精度;3、返回值。更多关于sprintf函数用法详解的内容,大家可以阅读下面的文章。

2023.11.27

11922

4

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Webman中文手册
Webman中文手册

共0课时 | 0人学习

Workerman官方手册
Workerman官方手册

共0课时 | 0人学习

ThinkPHP5.1完全开发手册
ThinkPHP5.1完全开发手册

共0课时 | 0人学习