liurunyu
2024-08-15 f7e731bdc2fce4445c0d22993134c6c2b07d207b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
package com.ruoyi.netty.communication;
 
 
import com.ruoyi.common.utils.netty.ApplicationContextRegister;
import com.ruoyi.common.utils.netty.ConcurrentHashMapBean;
import com.ruoyi.common.utils.netty.ConvertCode;
import com.ruoyi.common.utils.netty.NettyTool;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.AttributeKey;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.ApplicationContext;
 
/**
 * @author 86175
 */
@Slf4j
public class OptometerServerHandler extends SimpleChannelInboundHandler<byte[]> {
 
 
    ApplicationContext act = ApplicationContextRegister.getApplicationContext();
 
    //用于保存所有Channel对象
    public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
 
    //表示连接建立
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        //chanel可以理解成Connection
        Channel channel = ctx.channel();
        //广播消息给所有的客户端
        channelGroup.add(channel);
    }
 
 
    // 数据发送和接受
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, byte[] bytes) throws Exception {
        String receiveStr = ConvertCode.bytes2Str(bytes);
        log.info("info 得到的数据:" + receiveStr);
        // 添加 CRC16校验 添加了 高位 和低位
 
        //建立通讯通道
        Channel channel = channelHandlerContext.channel();
 
        //报文原始码
//        String  mangedata=receiveStr.substring(26,receiveStr.length()-6);
//        //序列号
//        String number=receiveStr.substring(8,12);
        channelGroup.forEach(ch -> {
            //表示当前连接 就是当前硬件客户端与服务器进行的连接
            if (channel == ch) {
                if ( !receiveStr.startsWith("aa") && receiveStr.substring(46,48).equals("85")){
                    //获取识别符
                    String Identifier = receiveStr.substring(46, 48);
                    // 获取设备编号
                    String stcd = receiveStr.substring(40, 46);
                    log.info("连接的Id为:" + channel.id().asLongText());
                    online(ch, stcd);
                    ConcurrentHashMapBean.channelMap.put(stcd, channel);
                    log.info("设备: " + stcd + "与channel已经注册成功");
                    log.info("map的字节数" + ConcurrentHashMapBean.channelMap.size());
                }
 
                // ConnectTOClient.write2Client("7e7e01020304050607", channel, "心跳");
 
                DecisionIdentifier.ScreenIdentifier(receiveStr,act);
            }
        });
        channel.flush();
    }
 
 
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        /*ctx.close();*/
        log.warn("exceptionCaught发生异常:");
        cause.printStackTrace();
    }
 
    //连接处于活动状态
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        log.info(channel.remoteAddress() + " 上线了");
    }
 
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        try {
            Channel channel = ctx.channel();
            //根据 channel 找到 map的 key 然后删掉 做到数据同步
            String stcd = NettyTool.getKeyByLoop(ConcurrentHashMapBean.channelMap, channel);
            log.info(" channelInactive---通道的设备号: " + NettyTool.getKeyByLoop(ConcurrentHashMapBean.channelMap, channel) + "下线");
            ConcurrentHashMapBean.channelMap.remove(stcd);
            log.info(channel.remoteAddress() + " 下线了");
 
        } catch (Exception e) {
        }
    }
 
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        try {
            Channel channel = ctx.channel();
            log.info(" 【硬件设备】 -" + channel.remoteAddress() + " 离开\n");
 
            //验证一下每次客户端断开连接,连接自动地从channelGroup中删除调。
            // System.out.println(channelGroup.size());
            //当客户端和服务端断开连接的时候,下面的那段代码netty会自动调用,所以不需要人为的去调用它
            channelGroup.remove(channel);
            //下线的设备编号
            String stcd = NettyTool.getKeyByLoop(ConcurrentHashMapBean.channelMap, channel);
            log.info("通道的设备号: " + NettyTool.getKeyByLoop(ConcurrentHashMapBean.channelMap, channel) + "下线");
            //根据stcd  删除 连接通道
            ConcurrentHashMapBean.channelMap.remove(stcd);
        } catch (Exception e) {
        }
    }
 
 
    /**
     * 上线一个用户
     *
     * @param channel
     * @param userId
     */
    public void online(Channel channel, String userId) {
        //先判断用户是否在web系统中登录?
        //这部分代码个人实现,参考上面redis中的验证
        ConcurrentHashMapBean.channelMap.put(userId, channel);
        AttributeKey<String> key = AttributeKey.valueOf("user");
        channel.attr(key).set(userId);
    }
 
 
}