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

com.iteaj.iot.client.handle.ClientServiceHandler Maven / Gradle / Ivy

The newest version!
package com.iteaj.iot.client.handle;

import com.iteaj.iot.*;
import com.iteaj.iot.client.*;
import com.iteaj.iot.client.component.SocketClientComponent;
import com.iteaj.iot.client.protocol.ClientInitiativeProtocol;
import com.iteaj.iot.client.protocol.ServerInitiativeProtocol;
import com.iteaj.iot.config.ConnectProperties;
import com.iteaj.iot.event.*;
import com.iteaj.iot.protocol.NoneDealProtocol;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.Attribute;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static com.iteaj.iot.CoreConst.CLIENT_CLOSED_TYPE;
import static com.iteaj.iot.CoreConst.CLIENT_KEY;

/**
 * 客户端业务处理器
 */
public class ClientServiceHandler extends SimpleChannelInboundHandler {

    private SocketClientComponent clientComponent;
    private Logger logger = LoggerFactory.getLogger(ClientServiceHandler.class);


    public ClientServiceHandler(SocketClientComponent clientComponent) {
        this.clientComponent = clientComponent;
        if (this.clientComponent == null) {
            throw new IllegalArgumentException("ClientProtocolHandle必填参数[ClientComponent]");
        }
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ClientMessage msg) throws Exception {
        try {
            String componentName = clientComponent.getName();
            final IotProtocolFactory protocolFactory = clientComponent.protocolFactory();
            if (protocolFactory == null) {
                String deviceSn = msg.getHead().getEquipCode();
                logger.error("客户端协议处理({}) 协议工厂不存在 - 设备编号: {}", componentName, deviceSn);
                return;
            }

            Protocol protocol = protocolFactory.getProtocol(msg);
            if (protocol == null) {
                String messageId = msg.getMessageId();
                String deviceSn = msg.getHead() != null ? msg.getHead().getEquipCode() : null;
                logger.warn("客户端协议处理({}) 获取不到协议 - 设备编号: {} - messageId: {}"
                        , componentName, deviceSn, messageId);
                return;
            }
            // 声明此协议不需要处理
            if (protocol instanceof NoneDealProtocol) {
                return;
            }

            // 服务端响应给客户端
            if (protocol instanceof ClientInitiativeProtocol) {
                ((ClientInitiativeProtocol) protocol).buildResponseMessage(msg);

                // 服务端主动调用客户端
            } else if (protocol instanceof ServerInitiativeProtocol) {
                ServerInitiativeProtocol serverInitiativeProtocol = (ServerInitiativeProtocol) protocol;
                serverInitiativeProtocol.setClientKey(ctx.channel().attr(CLIENT_KEY).get());
                serverInitiativeProtocol.buildRequestMessage();
            } else {
                logger.error("客户端协议处理({}) 错误协议 协议类型: {} - 说明: [{}]必须是[{}]的子类", componentName
                        , protocol.protocolType(), protocol.getClass().getSimpleName(), AbstractClientProtocol.class.getSimpleName());
            }

            // 需要执行业务
            if (protocol instanceof BusinessAction) {
                // 执行业务, 阻塞太长的业务需要自行处理, 否则将影响并发量
                final AbstractProtocol response = ((BusinessAction) protocol)
                        .exec(FrameworkManager.getHandleFactory());

                // 响应给服务端
                if (response != null) {
                    ctx.channel().writeAndFlush(response);
                }
            }

        } catch (Exception e) {
            this.exceptionCaught(ctx, e);
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        logger.error("客户端处理({}) 处理异常 - 错误信息: {} - 处理方式:已发送异常事件[{}], 创建监听器[{}]来监听异常事件"
                , clientComponent.getName(), cause.getMessage(),
                ExceptionEvent.class.getSimpleName(), ExceptionEventListener.class.getSimpleName(), cause);

        if (cause instanceof ProtocolException) {
            Object protocol = ((ProtocolException) cause).getProtocol();
            if (protocol instanceof ClientProtocol) {
                FrameworkManager.publishEvent(new ProtocolExceptionEvent((Protocol) protocol, cause.getCause()));
                return;
            }
        }

        // 发布异常事件
        ClientConnectProperties config = ctx.channel().attr(CLIENT_KEY).get();
        FrameworkManager.publishEvent(new ExceptionEvent(cause, config.connectKey()));
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        if (!clientComponent.isActivation(ctx.channel(), clientComponent)) {
            ctx.channel().close();
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        // 客户端重连
        ConnectProperties config = ctx.channel().attr(CLIENT_KEY).get();
        IotClient client = clientComponent.getClient(config);

        /**
         * 1. 此处必须判断客户端是否存在(因为有可能已经被移除)
         * 2. 判断是否是因为调用接口disconnect导致的断开连接 如果是则不进行重连
         */
        if (client instanceof SocketClient) {
            Attribute attr = ctx.channel().attr(CoreConst.CLIENT_CLOSED_NORMAL);
            // 如果是调用了disconnect或者close接口导致的断线则不进行重连
            if(Boolean.TRUE.equals(attr.get())) {
                Integer type = ctx.channel().attr(CLIENT_CLOSED_TYPE).get();
                if(type != null && type == 1) {// 正常关闭则移除客户端
                    clientComponent.removeClient(config);
                }

                if(logger.isDebugEnabled()) {
                    String typeName = type != null ? (type == 1 ? "close" : "disconnect") : "other";
                    logger.debug("客户端正常关闭({}) {} - 客户端:{} - 远程地址: /{}:{}"
                            , clientComponent.getName(), typeName, config, config.getHost(), config.getPort());
                }
            } else {
                /**
                 * 如果是超过设置的空闲时间断开
                 * @see ClientConnectProperties#getAllIdleTime()
                 * @see ClientConnectProperties#getReaderIdleTime()
                 * @see ClientConnectProperties#getWriterIdleTime()
                 */
                Long timeout = ctx.channel().attr(CoreConst.CLIENT_TIMEOUT_CLOSED).get();
                if(timeout != null) {
                    if(logger.isWarnEnabled()) {
                        logger.warn("客户端超时关闭({}) 读/写超时({}s) - 客户端: {} - 远程地址: /{}:{}"
                                , clientComponent.getName(), timeout, config, config.getHost(), config.getPort());
                    }
                } else {
                    if(logger.isWarnEnabled()) {
                        logger.warn("客户端关闭({}) 未知原因 - 客户端: {} - 远程地址: /{}:{}"
                                , clientComponent.getName(), config, config.getHost(), config.getPort());
                    }
                }

                // 重连
                ((SocketClient) client).reconnection();
            }

            // 发布掉线事件
            FrameworkManager.publishEvent(new StatusEvent(client, ClientStatus.offline, clientComponent));
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy