netty是java网络框架中非常有名,因为它把各种网络类型,阻塞非阻塞的都做了上层的抽象,非常值得学习,这边就先以一个简单的http server来做下实践,
主体的server代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| public static void main(String[] args) throws InterruptedException {
EventLoopGroup boss = new NioEventLoopGroup(); EventLoopGroup work = new NioEventLoopGroup(); try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(boss, work) .option(ChannelOption.SO_BACKLOG, 1024) .handler(new LoggingHandler(LogLevel.DEBUG)) .channel(NioServerSocketChannel.class) .childHandler(new HttpServerInitializer());
ChannelFuture f = bootstrap.bind(new InetSocketAddress(8082)).sync(); System.out.println("server start up on port 8080"); f.channel().closeFuture().sync(); } finally { boss.shutdownGracefully(); work.shutdownGracefully(); } }
|
然后来看下 HttpServerInitializer
1 2 3 4 5 6 7 8 9 10 11 12 13
| public class HttpServerInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { ChannelPipeline pipeline = socketChannel.pipeline(); pipeline.addLast(new HttpServerCodec()); pipeline.addLast(new HttpContentCompressor((CompressionOptions[]) null )); pipeline.addLast(new HttpServerExpectContinueHandler()); pipeline.addLast(new SimpleHttpServerHandler()); } }
|
实际的代码也是很简略,我们用一个hello world统一响应所有的请求
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| public class SimpleHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> { private static final byte[] CONTENT = { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' };
@Override public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); }
@Override protected void channelRead0(ChannelHandlerContext channelHandlerContext, HttpObject msg) throws Exception { System.out.println("channel read"); if (msg instanceof HttpRequest) { HttpRequest httpRequest = (HttpRequest) msg; boolean keepAlive = HttpUtil.isKeepAlive(httpRequest);
FullHttpResponse response = new DefaultFullHttpResponse(httpRequest.protocolVersion(), OK, Unpooled.wrappedBuffer(CONTENT));
response.headers() .set(CONTENT_TYPE, TEXT_PLAIN) .setInt(CONTENT_LENGTH, response.content().readableBytes());
if (keepAlive) { if (!httpRequest.protocolVersion().isKeepAliveDefault()) { response.headers().set(CONNECTION, KEEP_ALIVE); } } else { response.headers().set(CONNECTION, CLOSE); }
ChannelFuture future = channelHandlerContext.write(response);
if (!keepAlive) { future.addListener(ChannelFutureListener.CLOSE); } } }
@Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } }
|
上面就是这个简单的示例了,只是我在 channelRead0
入口建了个打印,但是这个再接收请求时会打印两次,可以作为个探讨题,我们下次来分析下