All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.feingto.iot.server.handler.TcpMessageHandler Maven / Gradle / Ivy

There is a newer version: 1.2.5.RELEASE
Show newest version
package com.feingto.iot.server.handler;

import com.feingto.iot.common.handler.DefaultChannelInboundHandler;
import com.feingto.iot.common.model.custom.*;
import com.feingto.iot.common.model.enums.MessageType;
import com.feingto.iot.server.cache.ChannelCache;
import com.google.common.collect.Maps;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelId;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import io.netty.util.ReferenceCountUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

/**
 * TCP 消息处理器
 *
 * @author longfei
 */
@Slf4j
@Sharable
@SuppressWarnings("unchecked")
public class TcpMessageHandler extends DefaultChannelInboundHandler {
    private static AtomicReference> lossCounters = new AtomicReference<>();

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        ChannelCache.getInstance().remove(ctx.channel().id().asLongText());
        super.channelInactive(ctx);
    }

    @Override
    public void handleMessage(ChannelHandlerContext ctx, Object msg) {
        lossCounters.updateAndGet(map -> map = (Map) Maps.newHashMap()
                .put(ctx.channel().id(), 0));
        byte protocol = ((BaseMessage) msg).protocol();
        try {
            if (protocol == MessageType.LOGIN.getValue()) {
                LoginMessage message = (LoginMessage) msg;
                log.debug(">>> login username: {}", message.username());
                ChannelCache.getInstance().put(ctx.channel().id().asLongText(), new MessageChannel()
                        .channel(ctx.channel())
                        .username(message.username()));
                ctx.channel().writeAndFlush(message.protocol(MessageType.LOGIN_RESPONSE.getValue()));
            } else {
                MessageChannel mqttChannel = ChannelCache.getInstance().get(ctx.channel().id().asLongText());
                if (mqttChannel == null) {
                    log.debug("客户端未登录");
                    return;
                }

                if (protocol == MessageType.SYSTEM.getValue()) {
                    // ctx.writeAndFlush(Unpooled.copiedBuffer(String.format("Hello world from server %s", counter).getBytes()));
                    ChannelCache.getInstance().push((SystemMessage) msg);
                } else if (protocol == MessageType.MESSAGE.getValue()) {
                    ctx.channel().writeAndFlush(((Message) msg).protocol(MessageType.MESSAGE_RESPONSE.getValue()));
                }
            }
        } finally {
            ReferenceCountUtil.release(msg);
        }
    }

    /**
     * 心跳检测
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent) {
            IdleStateEvent event = (IdleStateEvent) evt;
            if (event.state() == IdleState.READER_IDLE) {
                log.debug(">>> server reader idle");
                ChannelId channelId = ctx.channel().id();
                lossCounters.updateAndGet(map -> map = (Map) Maps.newHashMap()
                        .put(channelId, lossCounters.get().get(channelId) + 1));
                if (lossCounters.get().get(channelId) > 2) {
                    log.debug(">>> closed channel id: {}", ctx.channel().id());
                    ChannelCache.getInstance().remove(ctx.channel().id().asLongText());
                    ctx.channel().close();
                }
            }
        } else {
            super.userEventTriggered(ctx, evt);
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy