Netty
5 Netty HTTP Demo
要求:
Netty 服务器在 8090 端口监听,浏览器发出请求 http://localhost:9099/
服务器可以回复消息给客户端 "Hello! i am server … " , 并 对特定请求资源进行过滤.
server
public class NettyHttpServer {
public static void main(String[] args) {
EventLoopGroup boosGroup = null;
EventLoopGroup workGroup = null;
try {
// boosGroup 处理连接队列(SYNC)
boosGroup = new NioEventLoopGroup();
// workGroup 处理正真的事件(Accept)
workGroup = new NioEventLoopGroup();
// server 端辅助类
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap
.group(boosGroup,workGroup)
.channel(NioServerSocketChannel.class)
// backlog = SYNC + ACCEPT
.option(ChannelOption.SO_BACKLOG,8)
// 缓冲区大小:自适应,有一定的性能损耗
.option(ChannelOption.RCVBUF_ALLOCATOR, AdaptiveRecvByteBufAllocator.DEFAULT)
// 缓冲区池
.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
System.out.println("初始化 server 端 channel...");
ChannelPipeline pipeline = ch.pipeline();
pipeline
// decode encode
.addLast(new HttpServerCodec())
// 自定义的事件处理器
.addLast(new NettyHTTPServerHandler());
}
});
ChannelFuture channelFuture = serverBootstrap.bind("127.0.0.1", 9099).sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
boosGroup.shutdownGracefully();
workGroup.shutdownGracefully();
}
}
}
Handler
public class NettyHTTPServerHandler extends SimpleChannelInboundHandler<HttpObject> {
/**
* HttpObject 客户端和服务器端相互通讯的数据被封装成 HttpObject
* SimpleChannelInboundHandler 是一个 ChannelInboundHandlerAdapter 子类
*
* @param ctx
* @param msg
* @throws Exception
*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
// 每个浏览器都是独立的 channel pipline
System.out.println("ChannelHandlerContext: " + ctx );
System.out.println("channel: " + ctx.channel().hashCode() );
System.out.println("channel 的 pipeline : " + ctx.channel().pipeline().hashCode() );
System.out.println("pipeline: " + ctx.pipeline().hashCode() );
System.out.println("pipeline 的 channel: " + ctx.pipeline().channel().hashCode() );
System.out.println("server端的handler:" + ctx.handler());
if (msg instanceof HttpRequest){
System.out.println("msg 类型:" + msg.getClass());
System.out.println("客户端地址:" + ctx.channel().remoteAddress());
ByteBuf buffer = Unpooled.copiedBuffer("Hello! i am server ...", StandardCharsets.UTF_8);
//过滤掉请求图标请求
HttpRequest httpRequest = (HttpRequest) msg;
String uri = httpRequest.uri();
System.out.println("http uri:" + uri);
if("/favicon.ico".equals(uri)) return;
// 构造一个http响应
HttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,buffer);
response.headers()
.set(HttpHeaderNames.CONTENT_TYPE,"text/plain")
.set(HttpHeaderNames.CONTENT_LENGTH,buffer.readableBytes());
// 返回响应
ctx.writeAndFlush(response);
}
}
}
演示