netty聊天服务器搭建

服务端的代码

public class WebsocketServer {
    private Channel channel;
    private final EventLoopGroup bossGroup = new NioEventLoopGroup();
    private final EventLoopGroup workerGroup = new NioEventLoopGroup();
    private int port;
    public WebsocketServer(int port) {
        this.port = port;
    }
    public void run() throws Exception {
        try {
            //创建ServerBootstrap实例
            ServerBootstrap b = new ServerBootstrap();  
           //设置并绑定Reactor线程池
            b.group(bossGroup, workerGroup)
            //设置并绑定服务端Channel
             .channel(NioServerSocketChannel.class)  
             .childHandler(new WebsocketServerInitializer())   
             .option(ChannelOption.SO_BACKLOG, 128)           
             .childOption(ChannelOption.SO_KEEPALIVE, true);

            System.out.println("WebsocketChatServer Start:" + port);
            ChannelFuture f = b.bind(port).sync();
            channel = f.channel();
            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
            channel.closeFuture().syncUninterruptibly();
            System.out.println("WebsocketChatServer Stop:" + port);
        }
    }

    public void destroy() {
        if (channel != null){
            channel.close();
        }
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
        System.out.println("WebsocketChatServer Destroy:" + port);
    }


    public static void main(String[] args) throws Exception {

        int port=8888;
        new WebsocketServer(port).run();

    }
}

1 创建两个EventLoopGroup
实际就是Reactor线程池,负责调度和执行客户端的接入、网络读写事件的处理、用户自定义任务和定时任务的执行。通过ServerBootstrap的group方法将两个EventLoopGroup实例传入

它实际就是EventLoop的数组。EventLoop的职责是处理所有注册到本线程多路复用器Selector上的Channel,Selector的轮询操作由绑定的EventLoop线程run方法驱动,在一个循环体内循环执行。

网络请求在NioEventLoop中进行处理,它会把接收到的channel注册到一个EventLoop的selector中,以后这个channel的所有请求都由所注册的EventLoop进行处理,这也是Netty用来处理竞态关系的机制,即一个channel的所有请求都在一个线程中进行处理,也就不会存在跨线程的冲突,因为这些调用都线程隔离了

看下ServerBootstrap的group方法的源码

 /**
     * Set the {@link EventLoopGroup} for the parent (acceptor) and the child (client). These
     * {@link EventLoopGroup}'s are used to handle all the events and IO for {@link ServerChannel} and
     * {@link Channel}'s.
     */
    public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) {
        super.group(parentGroup);
        if (childGroup == null) {
            throw new NullPointerException("childGroup");
        }
        if (this.childGroup != null) {
            throw new IllegalStateException("childGroup set already");
        }
        this.childGroup = childGroup;
        return this;
    }

因为他又实现了父类的group方法
来看父类的group方法

/**
     * The {@link EventLoopGroup} which is used to handle all the events for the to-be-creates
     * {@link Channel}
     */
    @SuppressWarnings("unchecked")
    public B group(EventLoopGroup group) {
        if (group == null) {
            throw new NullPointerException("group");
        }
        if (this.group != null) {
            throw new IllegalStateException("group set already");
        }
        this.group = group;
        return (B) this;
    }

2 接下来设置并绑定服务端Channel。

channel(NioServerSocketChannel.class)

作为NIO服务端,需要创建ServerSocketChannel,Netty对原生的NIO类库进行了封装,对应实现是NioServerSocketChannel。
对于用户而言,不需要关心服务端Channel的底层实现细节和工作原理,只需要指定具体使用哪种服务端Channel即可。因此,Netty的ServerBootstrap方法提供了channel方法用于指定服务端Channel的类型。Netty通过工厂类,利用反射创建NioServerSocketChannel对象。
源码

 /**
     * The {@link Class} which is used to create {@link Channel} instances from.
     * You either use this or {@link #channelFactory(ChannelFactory)} if your
     * {@link Channel} implementation has no no-args constructor.
     */
    public B channel(Classextends C> channelClass) {
        if (channelClass == null) {
            throw new NullPointerException("channelClass");
        }
        return channelFactory(new BootstrapChannelFactory(channelClass));
    }

3 链路建立的时候创建并初始化ChannelPipeline

childHandler(new WebsocketServerInitializer()) 
public class WebsocketServerInitializer extends
        ChannelInitializer<SocketChannel> {

    @Override
    public void initChannel(SocketChannel ch) throws Exception {    
        ChannelPipeline pipeline = ch.pipeline();
        pipeline.addLast(new ServerHandler());
        pipeline.addLast(new HttpServerCodec());
        pipeline.addLast(new HttpObjectAggregator(64*1024));
        pipeline.addLast(new ChunkedWriteHandler());
        pipeline.addLast(new HttpRequestHandler("/ws"));
        pipeline.addLast(new WebSocketServerProtocolHandler("/ws")); 
    /*  pipeline.addLast(new IdleStateHandler(20, 0, 0));
        pipeline.addLast(new LengthFieldBasedFrameDecoder(1024, 0, 4, -4, 0)); */   
    }

你可能感兴趣的:(netty聊天服务器搭建)