modbus协议是7层结构中的应用层的一种请求应答协议
分为
1 串行链路上的MODBUS
MODBUS串行链路取决于TIA/EIA标准:232-F和485-A。
串行链路协议是一个主从协议,同一时刻只有一个主节点连接于总线,1个或多个子节点连接于一个串行总线。子节点间不会相互通信,主节点同一时刻只会发起一个modbus事务。
2 TCP/IP上的MODBUS
MODBUS TCP/IP取决于IETF标准:RFC793 和RFC791有关。
在TCP/IP上使用一种专用报文头识别MODBUS应用数据单元。将这种报文头称为MBAP报文
头(MODBUS 协议报文头)。
报文头为7 个字节长:
事务处理标识符:用于事务处理配对。在响应中,MODBUS服务器复制请求的事务处理标识符。
协议标识符:用于系统内的多路复用。通过值0 识别MODBUS 协议。
长度:长度域是下一个域的字节数,包括单元标识符和数据域。
单元标识符:为了系统内路由,使用这个域。专门用于通过以太网TCP-IP网络和MODBUS串
行链路之间的网关对MODBUS或MODBUS+串行链路从站的通信。MODBUS客户机在请求中设置
这个域,在响应中服务器必须利用相同的值返回这个域。
博主举个我实际应用的例子,下面是读取保持寄存器的报文
(1)0x00 (2)0x01 (3)0x00 (4)0x00 (5)0x00 (6)0x06 (7)0x01 (8)0x03 (9)0x00 (10)0x0B (11)0x00 (12)0x01
1,2 为客户端生成标识,服务端复制并返回
3,4 0代表modbus协议
5.6 长度,包括单元标识和数据域
7 从站识别码
8 功能码
9,10 起始地址
11,12 寄存器数量
下面是java代码,我是继承了modbus4j的框架
1 服务端
package com.serotonin.modbus4j.test;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import com.serotonin.modbus4j.sero.io.StreamUtils;
public class Test {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(502);
while (true)
new SocketThread(ss.accept());
}
static class SocketThread extends Thread {
Socket s;
InputStream in;
SocketThread(Socket s) {
System.out.println("Socket opened");
try {
this.s = s;
this.in = s.getInputStream();
start();
}
catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
byte[] b = new byte[1024];
int readcount;
try {
while (true) {
readcount = in.read(b);
if (readcount == -1)
break;
System.out.println(StreamUtils.dumpMessage(b, 0, readcount));
}
}
catch (IOException e) {
System.out.println(e.getMessage());
}
try {
if (s != null)
s.close();
}
catch (IOException e) {}
System.out.println("Socket closed");
}
}
// public static void main(String[] args) throws Exception {
// SerialParameters serialParameters = new SerialParameters();
// serialParameters.setCommPortId("COM1");
// serialParameters.setPortOwnerName("Numb nuts");
// serialParameters.setBaudRate(9600);
//
// ModbusFactory modbusFactory = new ModbusFactory();
//
// ModbusMaster master = modbusFactory.createRtuMaster(serialParameters, false);
// System.out.println("init 1");
// master.init();
// System.out.println("destroy 1");
// master.destroy();
//
// master = modbusFactory.createRtuMaster(serialParameters, false);
// System.out.println("init 2");
// master.init();
// System.out.println("destroy 2");
// master.destroy();
// }
}
2 客户端
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.code.DataType;
import com.serotonin.modbus4j.code.RegisterRange;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.locator.NumericLocator;
public class Test {
// public static void main(String[] args) {
// NumericLocator l = new NumericLocator(0, 0, 0, DataType.FOUR_BYTE_INT_UNSIGNED_SWAPPED);
// System.out.println(l.bytesToValue(new byte[] { (byte) 0xE8, 0x03, 0x00, 0x00 }, 0));
// }
// public static void main(String[] args) throws Exception {
// {
// ByteQueue b = new ByteQueue("01040000000271cb");
// EncapMessageParser parser = new EncapMessageParser(false);
// IncomingMessage m = parser.parseMessage(b);
// System.out.println(m);
// }
// {
// ByteQueue b = new ByteQueue("01040404d2162ed4f1");
// EncapMessageParser parser = new EncapMessageParser(true);
// IncomingMessage m = parser.parseMessage(b);
// System.out.println(m);
// }
// }
public static void main(String[] args) throws Exception {
ModbusFactory factory = new ModbusFactory();
IpParameters params = new IpParameters();
// params.setHost("127.0.0.1");
// params.setPort(502);
// params.setEncapsulated(true);
params.setHost("10.1.10.10");
params.setPort(12345);
params.setEncapsulated(false);
ModbusMaster master = factory.createTcpMaster(params, true);
// master.setRetries(4);
master.setTimeout(2000);
master.setRetries(0);
long start = System.currentTimeMillis();
try {
master.init();
for (int i = 0; i < 100; i++) {
System.out.println(master.getValue(new NumericLocator(1, RegisterRange.HOLDING_REGISTER, 11,
DataType.TWO_BYTE_INT_SIGNED)));//参数信息(从机号、寄存器功能码、偏移地址、数据类型)
}
}
finally {
master.destroy();
}
System.out.println("Took: " + (System.currentTimeMillis() - start) + "ms");
}
// public static void main(String[] args) throws Exception {
// ModbusFactory factory = new ModbusFactory();
// IpParameters params = new IpParameters();
// params.setHost("localhost");
// params.setPort(12345);
// ModbusMaster master = factory.createTcpMaster(params, true, false);
// // master.setRetries(4);
// master.setRetries(0);
// try {
// master.init();
// master.getValue(1, RegisterRange.HOLDING_REGISTER, 0, DataType.TWO_BYTE_INT_UNSIGNED);
// }
// finally {
// master.destroy();
// }
// }
}