TCP 服务端 数据解码
This commit is contained in:
parent
94f0251ca0
commit
e13552b692
12
pom.xml
12
pom.xml
|
|
@ -76,6 +76,18 @@
|
|||
<artifactId>mapper</artifactId>
|
||||
<version>4.1.5</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.mina</groupId>
|
||||
<artifactId>mina-core</artifactId>
|
||||
<version>2.2.3</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-all</artifactId>
|
||||
<version>4.1.68.Final</version>
|
||||
</dependency>
|
||||
<!-- poi -->
|
||||
<dependency>
|
||||
<groupId>org.apache.poi</groupId>
|
||||
|
|
|
|||
|
|
@ -8,12 +8,14 @@ import org.springframework.boot.SpringApplication;
|
|||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
|
||||
/**
|
||||
* @author 黑子
|
||||
*/
|
||||
@MapperScan({"com.bonus.aqd.*.*.dao", "com.bonus.aqd.*.dao"})
|
||||
@SpringBootApplication(exclude={MongoAutoConfiguration.class})
|
||||
@EnableAsync
|
||||
public class SpringBootSecurityApplication implements CommandLineRunner {
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
package com.bonus.aqd.base.dao;
|
||||
|
||||
import com.bonus.aqd.base.entity.DevVO;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* @author 黑子
|
||||
*/
|
||||
@Repository(value = "DevDataMapper")
|
||||
public interface DevDataMapper {
|
||||
|
||||
|
||||
/**
|
||||
* 更新双沟状态
|
||||
* @param devVO
|
||||
*/
|
||||
void updateData(DevVO devVO);
|
||||
|
||||
/**
|
||||
* 更新在线状态
|
||||
* @param devVO
|
||||
*/
|
||||
void updateDevStatus(DevVO devVO);
|
||||
|
||||
|
||||
/**
|
||||
* 更新在线状态
|
||||
* @param devVO
|
||||
*/
|
||||
void downDevStatus(DevVO devVO);
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
package com.bonus.aqd.base.entity;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 设备实体类
|
||||
* @author 黑子
|
||||
*/
|
||||
@Data
|
||||
public class DevVO {
|
||||
|
||||
private String devCode;
|
||||
|
||||
private String devA;
|
||||
|
||||
private String devB;
|
||||
|
||||
private String devStatus;
|
||||
|
||||
private String devAtime;
|
||||
|
||||
private String devBtime;
|
||||
|
||||
private String startTime;
|
||||
|
||||
private String devTime;
|
||||
/**
|
||||
* 通道id
|
||||
*/
|
||||
private String channId;
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,10 +1,16 @@
|
|||
package com.bonus.aqd.tcpservice;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import lombok.Data;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
|
|
@ -13,8 +19,16 @@ import java.net.InetSocketAddress;
|
|||
* @author 黑子
|
||||
*/
|
||||
@ChannelHandler.Sharable
|
||||
@Component
|
||||
@Slf4j
|
||||
public class BootNettyChannelInboundHandlerAdapter extends ChannelInboundHandlerAdapter {
|
||||
|
||||
|
||||
|
||||
|
||||
public SaveDataService service = SpringUtils.getBean(SaveDataService.class);
|
||||
|
||||
|
||||
/**
|
||||
* 注册时执行
|
||||
*/
|
||||
|
|
@ -22,7 +36,7 @@ public class BootNettyChannelInboundHandlerAdapter extends ChannelInboundHandler
|
|||
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
|
||||
//注册通道
|
||||
super.channelRegistered(ctx);
|
||||
System.out.println("--channelRegistered--" + ctx.channel().id().toString());
|
||||
System.out.println("--通道号注册--" + ctx.channel().id().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -32,7 +46,8 @@ public class BootNettyChannelInboundHandlerAdapter extends ChannelInboundHandler
|
|||
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
|
||||
//通道离线
|
||||
super.channelUnregistered(ctx);
|
||||
System.out.println("--channelUnregistered--" + ctx.channel().id().toString());
|
||||
System.out.println("--通道号离线--" + ctx.channel().id().toString());
|
||||
service.downDevStatus(ctx.channel().id().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -44,18 +59,24 @@ public class BootNettyChannelInboundHandlerAdapter extends ChannelInboundHandler
|
|||
if (msg == null) {
|
||||
return;
|
||||
}
|
||||
ByteBuf in = (ByteBuf) msg;
|
||||
byte[] bs = new byte[in.readableBytes()];
|
||||
in.readBytes(bs);
|
||||
String order = ByteUtil.bytesToHexString(bs);
|
||||
service.addDataInfo(order.trim());
|
||||
//转成String
|
||||
String data = (String) msg;
|
||||
String data =order;
|
||||
//替换掉 换行 和 空格
|
||||
data = data.replaceAll("\r|\n", "");
|
||||
//获取通道ID 并打印
|
||||
String channelId = ctx.channel().id().toString();
|
||||
System.out.println("channelId=" + channelId + "data=" + data);
|
||||
|
||||
System.err.println("通道号---> " + channelId + "--->数据---> " + data);
|
||||
// 这里我将通道id作为code来使用,实际是需要msg里来摘取的客户端数据里的唯一值的
|
||||
// 如果没有则创建 如果有,更新data值
|
||||
BootNettyChannel b = BootNettyChannelCache.get("server:" + channelId);
|
||||
if (b == null) {
|
||||
// 第一次更新状态
|
||||
service.updateDataStatus(order.trim(),channelId);
|
||||
//创建通道
|
||||
BootNettyChannel bnc = new BootNettyChannel();
|
||||
bnc.setChannel(ctx.channel());
|
||||
|
|
|
|||
|
|
@ -29,9 +29,11 @@ public class BootNettyChannelInitializer<SocketChannel> extends ChannelInitializ
|
|||
|
||||
ch.pipeline().addLast(new IdleStateHandler(READ_TIME_OUT, WRITE_TIME_OUT, ALL_TIME_OUT, TimeUnit.SECONDS));
|
||||
// 带编码
|
||||
ch.pipeline().addLast("encoder", new StringEncoder(CharsetUtil.UTF_8));
|
||||
ch.pipeline().addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));
|
||||
|
||||
// ch.pipeline().addLast("encoder", new StringEncoder(CharsetUtil.UTF_8));
|
||||
// ch.pipeline().addLast("decoder", new StringDecoder(CharsetUtil.UTF_8));
|
||||
// 在Netty的pipeline中添加
|
||||
ch.pipeline().addLast(new HexDecoder());
|
||||
// ch.pipeline().addLast(new StringDecoder(CharsetUtil.UTF_8));
|
||||
// // ChannelOutboundHandler,依照逆序执行
|
||||
// ch.pipeline().addLast("encoder", new StringEncoder());
|
||||
//
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import io.netty.channel.socket.SocketChannel;
|
|||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
|
||||
/**
|
||||
*
|
||||
* 蚂蚁舞
|
||||
* @author 黑子
|
||||
*/
|
||||
public class BootNettyServer {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
package com.bonus.aqd.tcpservice;
|
||||
|
||||
/**
|
||||
* @author 黑子
|
||||
*/
|
||||
public class ByteUtil {
|
||||
|
||||
public static byte[] hexString2Bytes(String src) {
|
||||
|
||||
int l = src.length() / 2;
|
||||
|
||||
byte[] ret = new byte[l];
|
||||
|
||||
for (int i = 0; i < l; i++) {
|
||||
ret[i] = (byte) Integer.valueOf(src.substring(i * 2, i * 2 + 2), 16).byteValue();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
public static String bytesToHexString(byte[] src) {
|
||||
StringBuilder stringBuilder = new StringBuilder("");
|
||||
if (src == null || src.length <= 0) {
|
||||
return null;
|
||||
}
|
||||
for (int i = 0; i < src.length; i++) {
|
||||
int v = src[i] & 0xFF;
|
||||
String hv = Integer.toHexString(v);
|
||||
if (hv.length() < 2) {
|
||||
stringBuilder.append(0);
|
||||
}
|
||||
stringBuilder.append(hv);
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
package com.bonus.aqd.tcpservice;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.handler.codec.ByteToMessageDecoder;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class HexDecoder extends ByteToMessageDecoder {
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
|
||||
ByteBuf buffer = ctx.alloc().buffer();
|
||||
while (in.isReadable()) {
|
||||
byte b = in.readByte();
|
||||
buffer.writeBytes(new byte[]{b});
|
||||
}
|
||||
out.add(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4,9 +4,6 @@ import io.netty.channel.ChannelHandlerContext;
|
|||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
/**
|
||||
* @author 黑子
|
||||
*/
|
||||
@Slf4j
|
||||
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
package com.bonus.aqd.tcpservice;
|
||||
|
||||
import org.apache.mina.core.service.IoHandlerAdapter;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
|
||||
/**
|
||||
* @author 黑子
|
||||
*/
|
||||
@Component
|
||||
public class ServerHandler extends IoHandlerAdapter {
|
||||
|
||||
@Autowired
|
||||
protected SaveDataService service;
|
||||
private static ServerHandler serverHandler ;
|
||||
@PostConstruct //通过@PostConstruct实现初始化bean之前进行的操作
|
||||
public void init() {
|
||||
serverHandler = this;
|
||||
serverHandler.service = this.service;
|
||||
// 初使化时将已静态化的testService实例化
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
package com.bonus.aqd.tcpservice;
|
||||
|
||||
import org.springframework.aop.framework.AopContext;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* spring工具类 方便在非spring管理环境中获取bean
|
||||
*
|
||||
* @author bonus
|
||||
*/
|
||||
@Component
|
||||
public final class SpringUtils implements BeanFactoryPostProcessor
|
||||
{
|
||||
/** Spring应用上下文环境 */
|
||||
private static ConfigurableListableBeanFactory beanFactory;
|
||||
|
||||
@Override
|
||||
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
|
||||
{
|
||||
SpringUtils.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对象
|
||||
*
|
||||
* @param name
|
||||
* @return Object 一个以所给名字注册的bean的实例
|
||||
* @throws BeansException
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T getBean(String name) throws BeansException
|
||||
{
|
||||
return (T) beanFactory.getBean(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取类型为requiredType的对象
|
||||
*
|
||||
* @param clz
|
||||
* @return
|
||||
* @throws BeansException
|
||||
*
|
||||
*/
|
||||
public static <T> T getBean(Class<T> clz) throws BeansException
|
||||
{
|
||||
T result = (T) beanFactory.getBean(clz);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
|
||||
*
|
||||
* @param name
|
||||
* @return boolean
|
||||
*/
|
||||
public static boolean containsBean(String name)
|
||||
{
|
||||
return beanFactory.containsBean(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
|
||||
*
|
||||
* @param name
|
||||
* @return boolean
|
||||
* @throws NoSuchBeanDefinitionException
|
||||
*
|
||||
*/
|
||||
public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
|
||||
{
|
||||
return beanFactory.isSingleton(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name
|
||||
* @return Class 注册对象的类型
|
||||
* @throws NoSuchBeanDefinitionException
|
||||
*
|
||||
*/
|
||||
public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
|
||||
{
|
||||
return beanFactory.getType(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果给定的bean名字在bean定义中有别名,则返回这些别名
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
* @throws NoSuchBeanDefinitionException
|
||||
*
|
||||
*/
|
||||
public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
|
||||
{
|
||||
return beanFactory.getAliases(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取aop代理对象
|
||||
*
|
||||
* @param invoker
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T getAopProxy(T invoker)
|
||||
{
|
||||
return (T) AopContext.currentProxy();
|
||||
}
|
||||
}
|
||||
|
|
@ -37,5 +37,5 @@ zhly:
|
|||
enable: false
|
||||
|
||||
netty:
|
||||
port: 6665
|
||||
port: 6666
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.bonus.aqd.base.dao.DevDataMapper">
|
||||
|
||||
|
||||
<update id="updateData" parameterType="com.bonus.aqd.base.entity.DevVO">
|
||||
update tb_device
|
||||
set dev_a=#{devA} ,dev_b=#{devB}
|
||||
<if test="devAtime!=null and devAtime!=''">
|
||||
, dev_a_time=#{devAtime}
|
||||
</if>
|
||||
<if test="devBtime!=null and devBtime!=''">
|
||||
, dev_b_time= #{devBtime}
|
||||
</if>
|
||||
,dev_time=now()
|
||||
where dev_code=#{devCode}
|
||||
</update>
|
||||
<update id="updateDevStatus" parameterType="com.bonus.aqd.base.entity.DevVO">
|
||||
update tb_device
|
||||
set dev_status=#{devStatus},
|
||||
<if test="channId!=null and channId!=''">
|
||||
chann_id= #{channId},
|
||||
</if>
|
||||
state_time=now(),
|
||||
dev_time=now()
|
||||
where dev_code=#{devCode}
|
||||
</update>
|
||||
<update id="downDevStatus" parameterType="com.bonus.aqd.base.entity.DevVO">
|
||||
update tb_device
|
||||
set dev_status=0, chann_id= #{channId}
|
||||
where chann_id=#{channId}
|
||||
</update>
|
||||
</mapper>
|
||||
Loading…
Reference in New Issue