

package fr.zng.xxzx.netty.pcws;


import fr.zng.xxzx.common.util.CommUtil;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.util.concurrent.ImmediateEventExecutor;

import java.net.InetAddress;
import java.net.InetSocketAddress;


/**
 * netty服务主入口
 * @author Allen
 * @date 2016年12月9日
 */
public final class PcWebSocketServer {

    public final static String KEY = "/ws";

    private final ChannelGroup group = new DefaultChannelGroup(
        ImmediateEventExecutor.INSTANCE);

    private final EventLoopGroup workerGroup = new NioEventLoopGroup();

    private Channel channel;


    private final ChannelFuture core(InetSocketAddress address) {
        ServerBootstrap boot = new ServerBootstrap();
        boot.group(workerGroup).channel(NioServerSocketChannel.class);
        boot.childHandler(new ChannelInitializer<Channel>() {

            @Override
            protected void initChannel(Channel channel) throws Exception {
                // 编码模块
                channel.pipeline().addLast("http-codec", new HttpServerCodec());
                // 大数据内容写入模块
                channel.pipeline().addLast("http-chunked", new ChunkedWriteHandler());
                // 组装Http头信息保证完整性
                channel.pipeline().addLast("aggregator", new HttpObjectAggregator(65536));
                // 上下文判断
//                channel.pipeline().addLast("handler", new WebSocketHandler());
                channel.pipeline().addLast("handler", new PcWebSocketServerHandler());
            }
        }).option(ChannelOption.SO_BACKLOG, 128)
          .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
          .childOption(ChannelOption.SO_KEEPALIVE, true)
          .childOption(ChannelOption.TCP_NODELAY, true);
        ChannelFuture f = boot.bind(address).syncUninterruptibly();
        channel = f.channel();
        return f;
    }


    /**
     * channel Group回收
     * @author Allen
     * @date 2016年12月13日
     */
    private void recovery() {

        CommUtil.doPrint("INFO", "NettyServer 资源回收");
        if (channel != null)
            channel.close();
        group.close();
        workerGroup.shutdownGracefully();
        CommUtil.doPrint("INFO", "NettyServer 资源回收完毕");
    }


    /**
     * 启动
     * @author Allen
     * @date 2016年12月13日
     */
    public final void run() {
        
        ChannelFuture f = core(new InetSocketAddress("127.0.0.1", 1111));
        // // 系统异常则进行回收
        Runtime.getRuntime().addShutdownHook(new Thread() {

            @Override
            public void run() {
                recovery();
            }
        });
        f.channel().closeFuture().syncUninterruptibly();

    }

    
    public static void  main(String[] args) {
    	PcWebSocketServer ws = new PcWebSocketServer();
    	ws.run();
    }
}