package websocketdemo.timeserver2; import io.netty.bootstrap.ServerBootstrap; 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.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.http.HttpServerCodec; /** * 通过端口调用关闭netty演示<br /> * 调用方法<br /> * new TimeServer(8080, 8081).run(); //8080, 正常工作商品, 8081, 关闭端口<br /> * http;//127.0.0.1:8081/close; //关闭netty * @author lizw */ public class TimeServer { private int port; private int port_shutdown; public TimeServer(int port) { this.port = port; } public TimeServer(int port, int port_shutdown) { this.port = port; this.port_shutdown = port_shutdown; } public void run() throws Exception { //用于常规端口的Group EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); //用于关闭端口的Group EventLoopGroup bossGroup2 = new NioEventLoopGroup(); EventLoopGroup workerGroup2 = new NioEventLoopGroup(); try { ServerBootstrap b=null; //常规netty服务 ServerBootstrap b2=null; //关闭netty服务 ChannelFuture f=null; ChannelFuture f2=null; { //常规端口服务器建立 System.out.println("start regular netty server thread"); b = new ServerBootstrap(); // (2) b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) // (3) .childHandler(new ChannelInitializer<SocketChannel>() { // (4) @Override public void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new TimeServerHandler()); } }) .option(ChannelOption.SO_BACKLOG, 128) // (5) .childOption(ChannelOption.SO_KEEPALIVE, true); // (6) // Bind and start to accept incoming connections. f = b.bind(port).sync(); // (7) } { //关闭netty应用服务器建立 System.out.println("start shutdown netty server thread"); b2 = new ServerBootstrap(); b2.group(workerGroup2, bossGroup2); b2.channel(NioServerSocketChannel.class); final EventLoopGroup[] group={workerGroup, bossGroup, workerGroup2, bossGroup2}; b2.childHandler(new ChannelInitializer() { @Override protected void initChannel(Channel ch) throws Exception { ch.pipeline().addLast(new HttpServerCodec()); ch.pipeline().addLast(new CloaseServerHandler(group)); } }); f2 = b2.bind(port_shutdown).sync(); } f.channel().closeFuture(); f2.channel().closeFuture(); System.out.println("netty服务器运行中"); } finally { } } public static void main(String[] args) throws Exception { System.out.println("main start"); int port=8080; int port_shutdown=8081; new TimeServer(port, port_shutdown).run(); System.out.println("main end"); } }
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package websocketdemo.timeserver2; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.EventLoopGroup; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.DefaultHttpRequest; import io.netty.handler.codec.http.FullHttpResponse; import static io.netty.handler.codec.http.HttpHeaders.Names.ACCEPT_RANGES; import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_LENGTH; import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE; import static io.netty.handler.codec.http.HttpHeaders.Names.DATE; import static io.netty.handler.codec.http.HttpHeaders.Names.SERVER; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import java.io.UnsupportedEncodingException; import java.util.Date; /** * 处理http请求, 用于判断 uri = "/close" 时关闭netty应用 * @author lizw */ public class CloaseServerHandler extends ChannelInboundHandlerAdapter { EventLoopGroup[] group; public CloaseServerHandler(EventLoopGroup[] group) { this.group = group; } /** * 处理http请求, 如果 uri = "/close" 则关闭服务器, 否则返回 404页面(BAD_GATEWAY) * @param ctx * @param msg * @throws Exception */ @Override public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception { super.channelActive(ctx); //To change body of generated methods, choose Tools | Templates. DefaultHttpRequest req=null; FullHttpResponse response=null; boolean isClose=false; if(msg instanceof DefaultHttpRequest){ req=(DefaultHttpRequest)msg; String uri=req.getUri(); if(0==uri.indexOf("/close")) isClose=true; } response=closeNetty(isClose); final ChannelFuture cf = ctx.writeAndFlush(response); // (3) if(!isClose) return; cf.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) { ctx.close(); System.out.println("服务器马上关闭"); for (EventLoopGroup g : group) { g.shutdownGracefully(); } System.out.println("服务器马上完成"); } }); } /** * 关闭netty请求的响应 * @param flag true - 关闭, false - 返回 404页面(BAD_GATEWAY) * @param FullHttpResponse */ private FullHttpResponse closeNetty(boolean flag) throws UnsupportedEncodingException{ FullHttpResponse response=null; if(flag){ String text=new String("服务器即将关闭"); ByteBuf buf = Unpooled.wrappedBuffer(text.getBytes("utf-8")); response=new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, buf); }else{ String text=new String("404"); ByteBuf buf = Unpooled.wrappedBuffer(text.getBytes("utf-8")); response=new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_GATEWAY, buf); } response.headers().set(CONTENT_TYPE, "text/html;charset=utf-8"); response.headers().set(CONTENT_LENGTH, response.content().readableBytes()); response.headers().set(DATE, new Date().toString()); response.headers().set(SERVER, "netty-4.0.29-Final"); response.headers().set(ACCEPT_RANGES, "bytes"); return response; } }