netty發送和接收數據handler處理器


 

netty發送和接收數據handler處理器 主要是繼承 SimpleChannelInboundHandler 和 ChannelInboundHandlerAdapter

  一般用netty來發送和接收數據都會繼承SimpleChannelInboundHandler和ChannelInboundHandlerAdapter這兩個抽象類,那么這兩個到底有什么區別呢?

  其實用這兩個抽象類是有講究的,在客戶端的業務Handler繼承的是SimpleChannelInboundHandler,而在服務器端繼承的是ChannelInboundHandlerAdapter

  最主要的區別就是SimpleChannelInboundHandler在接收到數據后會自動release掉數據占用的Bytebuffer資源(自動調用Bytebuffer.release())。而為何服務器端不能用呢,因為我們想讓服務器把客戶端請求的數據發送回去,而服務器端有可能在channelRead方法返回前還沒有寫完數據,因此不能讓它自動release。

 

handler處理器 內置 方法

channelActive

通道激活時觸發,當客戶端connect成功后,服務端就會接收到這個事件,從而可以把客戶端的Channel記錄下來,供后面復用

 

 

channelRead

這個必須用啊,當收到對方發來的數據后,就會觸發,參數msg就是發來的信息,可以是基礎類型,也可以是序列化的復雜對象。

 

 

channelReadComplete

channelRead執行后觸發

 

 

exceptionCaught

出錯是會觸發,做一些錯誤處理

 

繼承  ChannelInboundHandlerAdapter  具體的例子

復制代碼
/**
 *  netty服務器的監聽 處理器
 * 
 * @author flm 2017年10月27日
 */
public class IOHandler extends ChannelInboundHandlerAdapter {

    private static Logger log = Logger.getLogger(IOHandler.class);

    //netty AttributeKey 相對於 web session【重要】
    public static final AttributeKey<DeviceSession> KEY = AttributeKey.valueOf("IO"); 

    private Producer producer;
    
    
    public IOHandler(Producer producer){
        this.producer=producer;
    }

/**
     * 讀取數據
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        
        DeviceSession session = ctx.channel().attr(KEY).get();     // 檢測是否 自己注冊的 客戶端
        
        ByteBuf buffer=(ByteBuf) msg;
        
        if (buffer == null||session == null) {
            closeConnection(ctx); // 關閉連接
        }
        
        MsgEntity msgEntity = new MsgEntity(buffer); // 解碼  buffer 封裝  msgEntity
        log.info("# Accept Client data :"+msgEntity.toString());
        
        if (MsgType.UNKNOW == msgEntity.getMsgType()) {
            log.info("# 客戶端 發送數據 類型未定義... :"+msgEntity.toString());
            return;
        }
        
        if(!session.isActivity()){
            session.setActivity(true);
            session.setImei(msgEntity.getImei());
            SessionManager.getSingleton().addClient(session);
        }
        producer.putData(msgEntity);
        
    }

    
    
    /**
     * 客戶端 注冊
     */
    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        super.channelRegistered(ctx);
        
        log.info(String.format("# client registered...:   %s ...", ctx.channel()));
        
        DeviceSession session = new DeviceSession(ctx.channel());
        // 綁定客戶端到SOCKET
        ctx.channel().attr(KEY).set(session);
    }

    
    /**
     * 客戶端 失去連接
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception
    {
        super.channelInactive(ctx);
        
        log.info(String.format("# client out... : %s", ctx.channel()));
        DeviceSession session = ctx.channel().attr(KEY).getAndSet(null);
        
        // 移除  session 並刪除 該客戶端
        SessionManager.getSingleton().removeClient(session, true);
        
        if(session.getDeviceID() != null)
        {
          //  producer.onData(new Request(new RootMessage(MessageType.LOGOUT, null, null), session));
        }
        
    }

   
    /**
     * 心跳機制  用戶事件觸發
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception
    {
        if (evt instanceof IdleStateEvent)
        {
            IdleStateEvent e = (IdleStateEvent) evt;
            
            //檢測 是否 這段時間沒有和服務器聯系
            if (e.state() == IdleState.ALL_IDLE)
            {
                //檢測心跳
                checkIdle(ctx);
            }
        }
        
        super.userEventTriggered(ctx, evt);
    }
    

  /**
     * 報錯 處理事件
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
            throws Exception {
        
        log.error("# 客戶端連接  Netty 出錯...");
        cause.printStackTrace();
        //關閉連接
        closeConnection(ctx);
    }
    
    
復制代碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM