1. 程式人生 > >《netty》netty原始碼分析之ChannelPipeline和ChannelHandler

《netty》netty原始碼分析之ChannelPipeline和ChannelHandler

ChannelPipeline

ChannelPipeline是ChannelHandler的容器,他負責ChannelHandler的事件攔截.

 

 

 

    @Override
    public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
        final AbstractChannelHandlerContext newCtx;
        synchronized (this) {
            checkMultiplicity(handler);

            newCtx = newContext(group, filterName(name, handler), handler);

            addLast0(newCtx);

            // If the registered is false it means that the channel was not registered on an eventloop yet.
            // In this case we add the context to the pipeline and add a task that will call
            // ChannelHandler.handlerAdded(...) once the channel is registered.
            if (!registered) {
                newCtx.setAddPending();
                callHandlerCallbackLater(newCtx, true);
                return this;
            }

            EventExecutor executor = newCtx.executor();
            if (!executor.inEventLoop()) {
                newCtx.setAddPending();
                executor.execute(new Runnable() {
                    @Override
                    public void run() {
                        callHandlerAdded0(newCtx);
                    }
                });
                return this;
            }
        }
        callHandlerAdded0(newCtx);
        return this;
    }

 

    private void addLast0(AbstractChannelHandlerContext newCtx) {
        AbstractChannelHandlerContext prev = tail.prev;
        newCtx.prev = prev;
        newCtx.next = tail;
        prev.next = newCtx;
        tail.prev = newCtx;
    }

 

 

ChannelHandler

 

看個例子

/**
 * 
* Title: HelloServerHandler
* Description:  服務端業務邏輯
* Version:1.0.0  
* @author guokaige
* @date 2017-8-31
 */
public class NettyServerHandler extends SimpleChannelInboundHandler<String> {
    /*
     * 收到訊息時,返回資訊
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg)
            throws Exception {
        // 收到訊息直接列印輸出
        System.out.println("服務端接受的訊息 : " + msg);
        if("quit".equals(msg)){//服務端斷開的條件
            ctx.close();
        }
        Date date=new Date();
        // 返回客戶端訊息
        ctx.writeAndFlush(date+"\n");
    }

    /*
     * 建立連線時,返回訊息
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("連線的客戶端地址:" + ctx.channel().remoteAddress());
        ctx.writeAndFlush("客戶端"+ InetAddress.getLocalHost().getHostName() + "成功與服務端建立連線! \n");
        super.channelActive(ctx);
    }
}