(高级篇 Netty多协议开发和应用)第十章-Http协议开发应用(基于Netty的HttpServer和HttpClient的简单实现)
1.HttpServer
1 package nettyHttpTest; 2 3 4 5 import io.netty.bootstrap.ServerBootstrap; 6 import io.netty.channel.ChannelFuture; 7 import io.netty.channel.ChannelInitializer; 8 import io.netty.channel.ChannelOption; 9 import io.netty.channel.EventLoopGroup; 10 import io.netty.channel.nio.NioEventLoopGroup; 11 import io.netty.channel.socket.SocketChannel; 12 import io.netty.channel.socket.nio.NioServerSocketChannel; 13 import io.netty.handler.codec.http.HttpRequestDecoder; 14 import io.netty.handler.codec.http.HttpResponseEncoder; 15 16 public class HttpServer { 17 18 19 20 public void start(int port) throws Exception { 21 EventLoopGroup bossGroup = new NioEventLoopGroup(); 22 EventLoopGroup workerGroup = new NioEventLoopGroup(); 23 try { 24 ServerBootstrap b = new ServerBootstrap(); 25 b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) 26 .childHandler(new ChannelInitializer<SocketChannel>() { 27 @Override 28 public void initChannel(SocketChannel ch) throws Exception { 29 // server端发送的是httpResponse,所以要使用HttpResponseEncoder进行编码 30 ch.pipeline().addLast(new HttpResponseEncoder()); 31 // server端接收到的是httpRequest,所以要使用HttpRequestDecoder进行解码 32 ch.pipeline().addLast(new HttpRequestDecoder()); 33 ch.pipeline().addLast(new HttpServerInboundHandler()); 34 } 35 }).option(ChannelOption.SO_BACKLOG, 128) 36 .childOption(ChannelOption.SO_KEEPALIVE, true); 37 38 ChannelFuture f = b.bind(port).sync(); 39 40 f.channel().closeFuture().sync(); 41 } finally { 42 workerGroup.shutdownGracefully(); 43 bossGroup.shutdownGracefully(); 44 } 45 } 46 47 public static void main(String[] args) throws Exception { 48 HttpServer server = new HttpServer(); 49 System.out.println("Http Server listening on 8844 ..."); 50 server.start(8844); 51 } 52 }
2.HttpServerInboundHandler
1 package nettyHttpTest; 2 3 4 5 import static io.netty.handler.codec.http.HttpHeaders.Names.CONNECTION; 6 import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_LENGTH; 7 import static io.netty.handler.codec.http.HttpHeaders.Names.CONTENT_TYPE; 8 import static io.netty.handler.codec.http.HttpResponseStatus.OK; 9 import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1; 10 11 import io.netty.buffer.ByteBuf; 12 import io.netty.buffer.Unpooled; 13 import io.netty.channel.ChannelHandlerAdapter; 14 import io.netty.channel.ChannelHandlerContext; 15 import io.netty.handler.codec.http.DefaultFullHttpResponse; 16 import io.netty.handler.codec.http.FullHttpResponse; 17 import io.netty.handler.codec.http.HttpContent; 18 import io.netty.handler.codec.http.HttpHeaders; 19 import io.netty.handler.codec.http.HttpHeaders.Values; 20 import io.netty.handler.codec.http.HttpRequest; 21 22 public class HttpServerInboundHandler extends ChannelHandlerAdapter { 23 24 25 26 private HttpRequest request; 27 28 @Override 29 public void channelRead(ChannelHandlerContext ctx, Object msg) 30 throws Exception { 31 if (msg instanceof HttpRequest) { 32 request = (HttpRequest) msg; 33 34 String uri = request.getUri(); 35 System.out.println("Uri:" + uri); 36 } 37 if (msg instanceof HttpContent) { 38 HttpContent content = (HttpContent) msg; 39 ByteBuf buf = content.content(); 40 System.out.println(buf.toString(io.netty.util.CharsetUtil.UTF_8)); 41 buf.release(); 42 43 String res = "I am OK"; 44 FullHttpResponse response = new DefaultFullHttpResponse(HTTP_1_1, 45 OK, Unpooled.wrappedBuffer(res.getBytes("UTF-8"))); 46 response.headers().set(CONTENT_TYPE, "text/plain"); 47 response.headers().set(CONTENT_LENGTH, 48 response.content().readableBytes()); 49 if (HttpHeaders.isKeepAlive(request)) { 50 response.headers().set(CONNECTION, Values.KEEP_ALIVE); 51 } 52 ctx.write(response); 53 ctx.flush(); 54 } 55 } 56 57 @Override 58 public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { 59 ctx.flush(); 60 } 61 62 @Override 63 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 64 System.out.println(cause.getMessage()); 65 ctx.close(); 66 } 67 68 }
3.HttpClient
1 package nettyHttpTest; 2 3 import io.netty.bootstrap.Bootstrap; 4 import io.netty.buffer.Unpooled; 5 import io.netty.channel.ChannelFuture; 6 import io.netty.channel.ChannelInitializer; 7 import io.netty.channel.ChannelOption; 8 import io.netty.channel.EventLoopGroup; 9 import io.netty.channel.nio.NioEventLoopGroup; 10 import io.netty.channel.socket.SocketChannel; 11 import io.netty.channel.socket.nio.NioSocketChannel; 12 import io.netty.handler.codec.http.DefaultFullHttpRequest; 13 import io.netty.handler.codec.http.HttpHeaders; 14 import io.netty.handler.codec.http.HttpMethod; 15 import io.netty.handler.codec.http.HttpRequestEncoder; 16 import io.netty.handler.codec.http.HttpResponseDecoder; 17 import io.netty.handler.codec.http.HttpVersion; 18 19 import java.net.URI; 20 21 public class HttpClient { 22 public void connect(String host, int port) throws Exception { 23 EventLoopGroup workerGroup = new NioEventLoopGroup(); 24 25 try { 26 Bootstrap b = new Bootstrap(); 27 b.group(workerGroup); 28 b.channel(NioSocketChannel.class); 29 b.option(ChannelOption.SO_KEEPALIVE, true); 30 b.handler(new ChannelInitializer<SocketChannel>() { 31 @Override 32 public void initChannel(SocketChannel ch) throws Exception { 33 // 客户端接收到的是httpResponse响应,所以要使用HttpResponseDecoder进行解码 34 ch.pipeline().addLast(new HttpResponseDecoder()); 35 // 客户端发送的是httprequest,所以要使用HttpRequestEncoder进行编码 36 ch.pipeline().addLast(new HttpRequestEncoder()); 37 ch.pipeline().addLast(new HttpClientInboundHandler()); 38 } 39 }); 40 41 // Start the client. 42 ChannelFuture f = b.connect(host, port).sync(); 43 44 URI uri = new URI("http://127.0.0.1:8844"); 45 String msg = "Are you ok?"; 46 DefaultFullHttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, 47 uri.toASCIIString(), Unpooled.wrappedBuffer(msg.getBytes("UTF-8"))); 48 49 // 构建http请求 50 request.headers().set(HttpHeaders.Names.HOST, host); 51 request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.KEEP_ALIVE); 52 request.headers().set(HttpHeaders.Names.CONTENT_LENGTH, request.content().readableBytes()); 53 // 发送http请求 54 f.channel().write(request); 55 f.channel().flush(); 56 f.channel().closeFuture().sync(); 57 } finally { 58 workerGroup.shutdownGracefully(); 59 } 60 61 } 62 63 public static void main(String[] args) throws Exception { 64 HttpClient client = new HttpClient(); 65 client.connect("127.0.0.1", 8844); 66 } 67 }
4.HttpClientInboundHandler
1 package nettyHttpTest; 2 3 import io.netty.buffer.ByteBuf; 4 import io.netty.channel.ChannelHandlerAdapter; 5 import io.netty.channel.ChannelHandlerContext; 6 import io.netty.handler.codec.http.HttpContent; 7 import io.netty.handler.codec.http.HttpHeaders; 8 import io.netty.handler.codec.http.HttpResponse; 9 10 public class HttpClientInboundHandler extends ChannelHandlerAdapter { 11 12 @Override 13 public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { 14 if (msg instanceof HttpResponse) 15 { 16 HttpResponse response = (HttpResponse) msg; 17 System.out.println("CONTENT_TYPE:" + response.headers().get(HttpHeaders.Names.CONTENT_TYPE)); 18 } 19 if(msg instanceof HttpContent) 20 { 21 HttpContent content = (HttpContent)msg; 22 ByteBuf buf = content.content(); 23 System.out.println(buf.toString(io.netty.util.CharsetUtil.UTF_8)); 24 buf.release(); 25 } 26 } 27 }
服务器
客户端