频道
bg

Netty Modbus Proxy

coding一月 12, 20221mins
Netty Networking

Netty基础H1

请求响应H2

ChannelInboundHandlerAdapter 中调用ChannelHandlerContext 进行write、flush动作,然后经过一些列的OutboundHandler进行处理和转换,最终由ChannelOutboundBuffer 写到pipeline中。

writeH2

ctx.writeAndFlush 是往输出方向的下一个Handler写

ctx.channel().writeAndFlush 是从pipelined的尾部开始写

Netty中ctx.writeAndFlush与ctx.channel().writeAndFlush的区别 - 代码先锋网

Modbus基础H1

Modbus数据报文格式如下

java

/**
* Modbus TCP Frame Description
* - max. 260 Byte (ADU = 7 Byte MBAP + 253 Byte PDU)
* - Length field includes Unit Identifier + PDU
*
* <----------------------------------------------- ADU -------------------------------------------------------->
* <---------------------------- MBAP -----------------------------------------><------------- PDU ------------->
* +------------------------+---------------------+----------+-----------------++---------------+---------------+
* | Transaction Identifier | Protocol Identifier | Length | Unit Identifier || Function Code | Data |
* | (2 Byte) | (2 Byte) | (2 Byte) | (1 Byte) || (1 Byte) | (1 - 252 Byte |
* +------------------------+---------------------+----------+-----------------++---------------+---------------+
* @throws Exception
*/

数据帧由MBAP和PDU构成

  • MBAP 包含2个字节的事务编号、协议版本号、数据长度(包含后续的Slave 标识的长度以及PDU的长度)、Slave标识
  • PDU 2个字节的Function Code和数据区,不同的Function Code对应的对应的数据区稍有不同。

实现H1

java

public class ProxyHandler extends ChannelInboundHandlerAdapter {
private TcpMaster tcpMaster;
public ProxyHandler(String targetHost, Integer targetPort) throws ModbusInitException {
IpParameters ipParameters = new IpParameters();
ipParameters.setHost(targetHost);
ipParameters.setPort(targetPort);
tcpMaster = (TcpMaster) new ModbusFactory().createTcpMaster(ipParameters, (short)1, true);
tcpMaster.init();
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
if (msg instanceof ModbusFrame) {
ModbusFrame requestFrame = (ModbusFrame) msg;
ModbusRequest request = (ModbusRequest) requestFrame.getMessage();
ModbusFrame responseFrame = tcpMaster.callModbusMessageSync(request);
ModbusHeader header = responseFrame.getHeader();
ctx.writeAndFlush(new ModbusFrame(
new ModbusHeader(requestFrame.getHeader().getTransactionIdentifier(),
header.getProtocolIdentifier(),
header.getLength(),
header.getUnitIdentifier()),
responseFrame.getMessage()));
}
}
}

评论


新的评论

匹配您的Gravatar头像

Joen Yu

@2022 JoenYu, all rights reserved. Made with love.