Java netty之NioServerSocketChannel

来源:互联网 发布:mysql qps 和 tps 编辑:程序博客网 时间:2024/05/16 17:03

在上一篇文章中分析了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什么的吧。。。。


原创粉丝点击