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

org.zodiac.sdk.simplenetty.channel.NioServerSocketChannel Maven / Gradle / Ivy

There is a newer version: 1.6.8
Show newest version
package org.zodiac.sdk.simplenetty.channel;

import java.io.IOException;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.channels.spi.AbstractSelectableChannel;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.ExecutionException;

import org.zodiac.sdk.simplenetty.concurrent.ChannelPromise;
import org.zodiac.sdk.simplenetty.core.AbstractEventLoop;
import org.zodiac.sdk.simplenetty.core.EventExecutor;
import org.zodiac.sdk.simplenetty.core.EventLoop;
import org.zodiac.sdk.simplenetty.handler.ChannelInitializer;
import org.zodiac.sdk.simplenetty.handler.DefaultChannelHandlerContext;
import org.zodiac.sdk.simplenetty.handler.DefaultChannelPipeline;

public class NioServerSocketChannel extends AbstractNioChannel {

    private volatile static Unsafe unsafe;
    private ServerSocketChannel serverSocketChannel;
    private NioServerSocketChannel that = this;

    public NioServerSocketChannel(EventLoop loop) {
        super(loop);
        unsafe();
    }

    @Override
    public AbstractSelectableChannel javaChannel() {
        return serverSocketChannel;
    }

    @Override
    public boolean isOpen() {
        return serverSocketChannel.isOpen();
    }

    @Override
    public boolean isRegistered() {
        return serverSocketChannel.isRegistered();
    }

    @Override
    public boolean isActive() {
        return this.isOpen() && serverSocketChannel.socket().isBound();
    }

    @Override
    public SocketAddress localAddress() {
        return unsafe().localAddress();
    }

    @Override
    public SocketAddress remoteAddress() {
        return unsafe().remoteAddress();
    }

    @Override
    public Unsafe unsafe() {
        if (unsafe == null) {
            synchronized (NioServerSocketChannel.class) {
                if (unsafe == null) {
                    return new UnsafeImpl();
                }
            }
        }
        return unsafe;
    }

    class UnsafeImpl implements Unsafe {

        public UnsafeImpl() {
            try {
                serverSocketChannel = ServerSocketChannel.open();
                serverSocketChannel.configureBlocking(false);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public SocketAddress localAddress() {
            try {
                return serverSocketChannel.getLocalAddress();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        public SocketAddress remoteAddress() {
            throw new UnsupportedOperationException("serverSocketChannel not support remoteAddress");
        }

        @Override
        public void bind(SocketAddress address, ChannelPromise promise) {
            try {
                serverSocketChannel.bind(address);
                ChannelPromise p = null;
                p = eventLoop.register(that, SelectionKey.OP_ACCEPT);
                key = p.get();
                synchronized (eventLoop.getExecutor()) {
                    eventLoop.getExecutor().notifyAll();
                }

                eventLoop.parent().list().forEach(item -> {
                    if (item != eventLoop) {
                        item.execute(() -> {
                            run((AbstractEventLoop)item);
                            return null;
                        });
                    }
                });
                run(eventLoop);
                // bind成功 写成功
            } catch (IOException | InterruptedException | ExecutionException e) {
                try {
                    javaChannel().close();
                    promise.setFail(e);
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }

        private void run(AbstractEventLoop eventLoop) {
            try {
                while (isActive()) {
                    int select = eventLoop.getSelector().select(2000);
                    if (select < 1) {
                        continue;
                    }
                    Set keys = eventLoop.getSelector().selectedKeys();
                    Iterator keyIterator = keys.iterator();
                    while (keyIterator.hasNext()) {
                        SelectionKey key = keyIterator.next();
                        if (!key.isValid()) {
                            continue;
                        }
                        if (key.isAcceptable()) {
                            accept();
                        }
                        keyIterator.remove(); // 该事件已经处理,可以丢弃
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        protected void accept() {
            try {
                SocketChannel socketChannel = serverSocketChannel.accept();
                if (socketChannel == null) {
                    return;
                }
                socketChannel.configureBlocking(false);
                AbstractEventLoop loop = (AbstractEventLoop)eventLoop.bootstrap().getChild().get();
                ChannelInitializer initializer = eventLoop.bootstrap().getInitializer();
                if (loop.getExecutor().getState() > EventExecutor.RUNNING) {
                    loop.setExecutor(new EventExecutor());
                }
                loop.execute(() -> {
                    try {
                        NioSocketChannel nioSocketChannel = new NioSocketChannel(loop, socketChannel);
                        DefaultChannelHandlerContext context =
                            new DefaultChannelHandlerContext(nioSocketChannel, eventLoop, eventLoop.parent());
                        nioSocketChannel.setContext(context);
                        DefaultChannelPipeline pipeline = new DefaultChannelPipeline();
                        pipeline.setContext(context);
                        context.setPipeline(pipeline);
                        initializer.init(context);
                        nioSocketChannel.run();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    return null;
                });
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void connect(SocketAddress address, ChannelPromise promise) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void write(ByteBuffer buffer) {
            throw new UnsupportedOperationException();
        }

        @Override
        public void flush() {
            throw new UnsupportedOperationException();
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy