Java netty之NioServerSocketChannel

在上一篇文章中分析了AbstractNioChannel,那么在这一篇文章中就分析一个具体的NioChannel类。。。

NioServerSocketChannel类用过netty的应该都比较熟悉吧,如果做服务器端的编程,那么我们一般情况下都是使用的这种类型的channel。


按照惯例,我们还是先来分析一下它的继承体系:

NioServerSocketChannel直接继承自AbstractNioMessageChannel,而AbstractNioMessageChannel则直接继承自AbstractNioChannel,

在这里先分析一下AbstractNioMessageChannel:

    @Override
    protected AbstractNioUnsafe newUnsafe() {
        return new NioMessageUnsafe();
    }
这个方法比较重要吧,这里就是真正的创建UnSafe对象了,在AbstractNioMessageChannel中定义了NioMessageUnsafe类型,在其中定义具体的read方法:
        public void read() {
            assert eventLoop().inEventLoop();
            final SelectionKey key = selectionKey();   //获取select key
            if (!config().isAutoRead()) {
                // only remove readInterestOp if needed
                key.interestOps(key.interestOps() & ~readInterestOp);
            }

            final ChannelPipeline pipeline = pipeline();  //获取pipeline
            final MessageBuf<Object> msgBuf = pipeline.inboundMessageBuffer();   //获取存放读取数据的buffer
            boolean closed = false;
            boolean read = false;
            boolean firedChannelReadSuspended = false;
            try {
                for (;;) {
                    int localReadAmount = doReadMessages(msgBuf);    //其实还是调用doReadMessages方法来读取数据,并将它保存到buffer当中去
                    if (localReadAmount > 0) {
                        read = true;
                    } else if (localReadAmount == 0) {
                        break;
                    } else if (localReadAmount < 0) {
                        closed = true;
                        break;
                    }
                }
            } catch (Throwable t) {
                if (read) {
                    read = false;
                    pipeline.fireInboundBufferUpdated();
                }

                if (t instanceof IOException) {
                    closed = true;
                } else if (!closed) {
                    firedChannelReadSuspended = true;
                    pipeline.fireChannelReadSuspended();
                }

                pipeline().fireExceptionCaught(t);
            } finally {
                if (read) {
                    pipeline.fireInboundBufferUpdated();
                }
                if (closed && isOpen()) {
                    close(voidFuture());
                } else if (!firedChannelReadSuspended) {
                    pipeline.fireChannelReadSuspended();
                }
            }
        }
    }
代码还是比较的简单吧,首先先后去selectkey,然后从pipeline中获取用于存读取数据的buffer,最后再调用doReadMessages方法来真正的读取数据,这个方法在当前的AbstractNioMessageChannel中并没有实现,而是留给了以后具体的类。
    @Override
    protected void doFlushMessageBuffer(MessageBuf<Object> buf) throws Exception {
        final int writeSpinCount = config().getWriteSpinCount() - 1;  //总共有多少个buffer需要写
        while (!buf.isEmpty()) {
            boolean wrote = false;
            for (int i = writeSpinCount; i >= 0; i --) {
                int localFlushedAmount = doWriteMessages(buf, i == 0);   //其实还是调用doWriteMessages方法来发送数据
                if (localFlushedAmount > 0) {
                    wrote = true;
                    break;
                }
            }

            if (!wrote) {
                break;
            }
        }
    }
该方法用于写数据,其实最终也是调用doWriteMessages方法来具体的写数据,而这个方法在当前AbstractNioMessageChannel中也并没有实现,也要等到以后实现。。。


好了,接下来分析NioServerSocketChannel类,首先来看它的构造方法:

    public NioServerSocketChannel() {
    	//在这里,新创建的ServerSocketChannel就是哪个SlectableChannel了
        super(null, null, newSocket(), SelectionKey.OP_ACCEPT);
        config = new DefaultServerSocketChannelConfig(this, javaChannel().socket());
    }
这个应该比较简单吧,调用了newSocket方法来创建具体的channel,这是一个类方法,我们来看看它的定义:
    private static ServerSocketChannel newSocket() {
        try {
            return ServerSocketChannel.open();    //这里就是创建ServerSocketChannel了
        } catch (IOException e) {
            throw new ChannelException(
                    "Failed to open a server socket.", e);
        }
    }
用过java nio的就应该比较熟悉了,这里是创建一个nio 的serversocketchannel对象,也就是在前面AbstractNioChannel中有提到过的SelectableChannel,另外这该类中实现了doReadMessages方法:
    @Override
    protected int doReadMessages(MessageBuf<Object> buf) throws Exception {
    	//其实serverchannel的读取,无非就是accept函数啊
        SocketChannel ch = javaChannel().accept();

        try {
            if (ch != null) {
                buf.add(new NioSocketChannel(this, null, ch));//将获取的socektchannel放入到buffer当中去
                return 1;
            }
        } catch (Throwable t) {
            logger.warn("Failed to create a new channel from an accepted socket.", t);

            try {
                ch.close();
            } catch (Throwable t2) {
                logger.warn("Failed to close a socket.", t2);
            }
        }

        return 0;
    }
很简单吧,其实serverchannel读数据不就是accept方法嘛,至于其他的传输数据的方法,向doConnect,write什么的就直接抛出异常就是了,serverchannel怎么能有这些方法呢。。。


好了,NioServerSocketChannel已经分析的差不多了,接下来该分析什么呢,貌似不知道啊。。。应该是NioSocketChannel,pipeline,promise什么的吧。。。。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值