You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用POCO C++库时同一TCP连接无法发送多个Modbus请求咨询

问题解答

两种实现的优劣对比

复用TCP连接的方案更优,原因如下:

  • 短连接每次建立、释放连接都需要经过三次握手、四次挥手流程,额外网络开销大,请求延迟更高。
  • 频繁建立短连接会产生大量TIME_WAIT状态的端口,高并发场景下容易出现端口耗尽、连接失败的问题。
  • Modbus TCP协议原生支持长连接复用,长连接是工业场景下的标准使用方式,仅在部分兼容性场景下才会使用短连接方案。

复用连接仅第一条请求生效的原因

这个问题是典型的Modbus TCP交互逻辑不规范导致的:
绝大多数Modbus TCP从站设备遵循请求-响应的同步交互模型,不支持在未返回前一个请求响应的情况下,批量接收多条请求(即不支持流水线请求)。你连续发送三条请求时,从站仅处理第一条,后续请求会被直接丢弃,就会出现只有第一个线圈置位成功的现象。
部分低端Modbus设备的TCP协议栈实现简陋,无法正确处理TCP粘包场景下的多Modbus帧解析,也会导致后续请求无法被识别。

修复方案

方案1:遵循请求-响应交互逻辑

每发送一条请求后,先读取从站返回的响应,再发送下一条请求,示例代码如下:

Poco::Net::SocketAddress sa("192.168.2.55", 502);
Poco::Net::StreamSocket socket;
socket.connect(sa);
unsigned char recvBuf[256];

// 置位线圈5
socket.sendBytes(/*set coil 5 to 1*/, 12);
socket.receiveBytes(recvBuf, sizeof(recvBuf)); // 接收当前请求的响应

// 置位线圈6
socket.sendBytes(/*set coil 6 to 1*/, 12);
socket.receiveBytes(recvBuf, sizeof(recvBuf));

// 置位线圈7
socket.sendBytes(/*set coil 7 to 1*/, 12);
socket.receiveBytes(recvBuf, sizeof(recvBuf));

socket.close();

生产环境建议进一步解析响应中的MBAP事务ID,确保收到的响应和当前发送的请求匹配,避免乱序导致的逻辑错误。

方案2:使用批量写线圈功能码

如果你的从站支持Modbus功能码0x0F(写多个线圈),可以将三个线圈的置位操作合并为一条请求发送,不仅能避免上述问题,还能进一步提升通信效率。

方案3:确认发送完整性

POCO的sendBytes方法返回实际发送的字节数,可能出现小于传入长度的情况,建议添加循环逻辑确保12字节请求完全发送后再进行后续操作。

内容的提问来源于stack exchange,提问作者X Y

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 18:36:05