刚开始用这个玩意的时候,很多东西不是很了解,所以走了很多弯路,大概记录一下。
推荐大家去看看这篇博客,当初也是因为看了这篇博客,才知道自己理解错误的地方:点击打开链接
/**
* 解码线程
*
* @author 郭鹏飞
*
*/
public class DecodeHandler {
private IoSession session; // 客户端连接类
public String allData = ""; // 完整数据包
public String remainData = ""; // 剩余的数据
private boolean dataHead = true; // 是否验证了数据长度
private byte[] head = {}; // 获取到数据头
private int msgLength = 0; // 获取到数据的长度
private boolean recHand = false; // 接收到握手包
private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public DecodeHandler(IoSession session) {
this.session = session;
}
/**
* 消息编码处理
*
* @param data
* @return
*/
public boolean handleData(String data) {
//自定义处理逻辑
remainData = "";
try {
String str = HexUtil.hex2String(data);
/* RTU心跳截取 */
if (str.length() >= 2 && str.substring(0, 2).equals("FE")) {
String tem = data;
tem = data.substring(0, 4);
remainData = data.substring(4);
allData = tem;
return true;
}
/* RTU开闸确认指令 */
if (data.length() == 16 || data.length() == 26) {
allData += data;
return true;
}
byte[] msgByte = HexUtil.hexString2Bytes(data);
/* 未接收到握手包的设备信息 */
if (!recHand && msgByte[0] == '[') {
int x = data.indexOf("5D");
String tem = data;
tem = data.substring(0, x + 2);
remainData = data.substring(x + 2);
allData = tem;
recHand = true;
return true;
}
// 如果未验证数据长度
if (dataHead) {
//验证数据长度
}
allData += data;
if (msgLength <= 0 || msgLength > 150) {
initDecode();
return true;
}
// 接收完整数据
else{
if (allData.length() / 2 >= msgLength) {
String tem = allData;
tem = allData.substring(0, msgLength * 2);
remainData = allData.substring(msgLength * 2);
allData = tem;
initDecode();
return true;
} else {
return false;
}
}
} catch (Exception e) {
e.printStackTrace();
System.out.println(sdf.format(new Date()) + "========================RTU解码器异常=====================");
return true;
}
/**
* 初始化数据
*/
private void initDecode() {
this.msgLength = 0;
this.dataHead = true;
}
}
/**
* RTU解码工厂
*
* @author 郭鹏飞
*
*/
public class MyProtocalDecoder extends CumulativeProtocolDecoder {
private final String charset;
public MyProtocalDecoder(String charset) {
this.charset = charset;
}
/**
* 解码接收到的消息
*/
@Override
protected synchronized boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out)
throws Exception {
String nowData = in.getHexDump(); // 接收16进制数据
nowData = nowData.replace(" ", "");
System.out.println("本次接收到的数据:" + nowData);
DecodeHandler dh = DecodeManage.getInstance().getValueBykey(session);
// 存在该客户端的解码处理方法
if (dh == null) {
dh = new DecodeHandler(session);
DecodeManage.getInstance().putValue(session, dh);
}
if (dh.handleData(nowData)) {
out.write(dh.allData);
System.out.println("RTU平台剩余数据长度:"+dh.remainData.length());
if (dh.remainData != null && !dh.remainData.equals("")) {
in.position(in.limit() - dh.remainData.length() / 2);
dh.allData = "";
return true;
} else {
in.position(in.limit());
dh.allData = "";
return false;
}
} else {
in.position(in.limit());
return false;
}
}
}
/**
* 解码器线程管理类
* @author guopengfei
*
*/
public class DecodeManage {
private static DecodeManage dm;
private DecodeManage(){}
public static DecodeManage getInstance(){
if(dm == null){
synchronized (DecodeManage.class) {
if(dm == null)
dm = new DecodeManage();
}
}
return dm;
}
public static Map map = new HashMap(); // 客户端连接池
/**
* 根据值获取键
* @param dt
* @return
*/
public IoSession getKeyByValue(DecodeHandler dt) {
for (IoSession key : map.keySet()) {
DecodeHandler is = map.get(key);
if (is.equals(dt))
return key;
}
return null;
}
/**
* 获取一个客户端解码线程
*
* @param key
* @return
*/
public synchronized DecodeHandler getValueBykey(IoSession key) {
return map.get(key);
}
/**
* 删除一个客户端解码线程
*
* @param key
*/
public synchronized void removebyKey(IoSession key) {
map.remove("");
map.remove(key);
}
/**
* 添加一个客户端解码线程
*
* @param key
* @param dt
*/
public synchronized void putValue(IoSession key, DecodeHandler dt) {
map.put(key, dt);
}
/**
* 查看容器数量
*
* @return
*/
public int getMapSize() {
return map.size();
}
}
SocketSessionConfig cfg = (SocketSessionConfig) session.getConfig();
session.getConfig().setIdleTime(IdleStatus.BOTH_IDLE, 300);
cfg.setSoLinger(0);
@Override
public void sessionClosed(IoSession session) throws Exception {
System.out.println(session.getRemoteAddress()+"===================的连接关闭了");
String eqNo = RTUClientManage.getInstance().getKeyByValue(session);
RTUClientManage.getInstance().removebyKey(eqNo);
DecodeManage.getInstance().removebyKey(session);
System.out.println(sdf.format(new Date()) + " RTU设备连接断开,设备的地址:" + session.getRemoteAddress() + "\n");
if (session != null) {
session.closeNow();
}
}
/**
* 接收到消息
*
* @param session
* @param message
* @throws Exception
*/
@Override
public synchronized void messageReceived(IoSession session, Object message) throws Exception {
String msg = message.toString();
if (msg != null) {
String head = HexUtil.subStr(data);
if (head != null && !head.equals("") && data.length() < 20 && data.startsWith("[") && data.endsWith("]")) {
handData = head;
// 添加到客户端管理类中
RTUClientManage.getInstance().putValue(handData, session);
System.out.println(sdf.format(new Date()) + " 接收到RTU设备" + session.getRemoteAddress() + "握手包了,握手包为为:"
+ handData + "=================绑定成功================");
System.out.println("================================================ 正在连接的RTU客户端数量为:"
+ RTUClientManage.getInstance().getMapSize());
} else {
//业务逻辑处理
}
}
}
package com.ts.handler;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import org.apache.mina.core.session.IoSession;
import com.ts.util.HexUtil;
/**
* 客户端管理类
*
* @author 郭鹏飞
*
*/
public class RTUClientManage {
private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
private volatile static RTUClientManage rc;
private RTUClientManage() {
}
/**
* 单例化管理类
*
* @return
*/
public static RTUClientManage getInstance() {
if (rc == null) {
synchronized (RTUClientManage.class) {
if (rc == null) {
rc = new RTUClientManage();
}
}
}
return rc;
}
public static Map map = new HashMap(); // 客户端连接池
public String getKeyByValue(IoSession session) {
for (String key : map.keySet()) {
IoSession is = map.get(key);
if (is.equals(session))
return key;
}
return null;
}
/**
* 获取一个客户端
*
* @param key
* @return
*/
public synchronized IoSession getValueBykey(String key) {
return map.get(key);
}
/**
* 删除一个客户端
*
* @param key
*/
public synchronized void removebyKey(String key) {
map.remove("");
map.remove(key);
}
/**
* 添加一个客户端
*
* @param key
* @param rsh
*/
public synchronized void putValue(String key, IoSession rsh) {
IoSession session = map.get(key);
if(session != null){
removebyKey(key);
session.closeNow();
}
map.put(key, rsh);
}
/**
* 查看容器数量
*
* @return
*/
public int getMapSize() {
return map.size();
}
}