1.Netty简介
netty是一个异步的事件驱动的网络框架。扩展的事件模型
统一的API
零拷贝
为什么放弃了Netty5?
使用了ForkJoinPool,但是性能没有明显提升,因此将其废弃掉了。
Netty的doc?Netty API Reference (4.1.56.Final)netty.io
学习大纲netty简介
netty架构实现
netty模块分析
nettyHttp Tunnel
Netty对Socket的实现
Netty压缩与解压缩
Netty对RPC的支援
WebScoket实现和原理分析
WebSocket连接、建立方式和生命周期
WebSocket服务端和客户端的开发
RPC框架分析
GOOGLE PROTOBUF 使用方式分析
Thrift使用方式和文件编写方式分析
Netty大文件传送支持
可扩展的事件模型
Netty统一通信API
零拷贝在Netty中的实现和支持
TCP粘包和拆包分析
NIO在Netty中的实现
Netty编解码开发技术
Netty重要的类和接口源码分析
Channel分析
序列化讲解
Netty实现Http服务器Demo
主程序的实现
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/*** 测试服务器* 功能描述:基于netty,客户端发出请求,服务端返回一个hello world** @author 荀彧 2021/1/5*/
public class TestServer {
private static final int PORT = 8080;
public static void main(String[] args) throws Exception {
// 定义两个事件循环组。 // NioEventLoopGroup 可以理解为死循环。 // bossGroup寓意不断从客户端接收连接,但是不对连接进行处理。交由workerGroup处理 EventLoopGroup bossGroup = new NioEventLoopGroup();
// workerGroup 进行处理。 EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
// ServerBootstrap 是 netty提供的比较方便启动的服务类 ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
// 子处理器,我们自己编写的,对请求进行处理 .childHandler(new TestServerInitializer());
ChannelFuture channelFuture = serverBootstrap.bind(PORT).sync();
channelFuture.channel().closeFuture().sync();
}finally {
// 出现异常之后,优雅关闭 bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
基本上Netty的使用就是这么几个流程:定义两个事件循环组。其中NioEventLoopGroup 可以理解为死循环。bossGroup寓意不断从客户端接收连接,但是不对连接进行处理。交由workerGroup处理。
定义ServerBootstrap,ServerBootstrap 是 netty提供的比较方便启动的服务类。
定义子处理器,对请求进行处理。
TestServerInitializer的实现
/*** @author 荀彧 2021/1/5*/
public class TestServerInitializer extends ChannelInitializer {
/*** 连接被创建之后,就会执行这个方法。是一个回调方法* @param ch* @throws Exception*/
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// 里面有很多的channelHandler,相当于拦截器 ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast("httpServerCodec",new HttpServerCodec());
pipeline.addLast("testHttpServerHandler",new TestHttpServerHandler());
}
}
在我们定义的TestServerInitializer中,我们可以添加自己的channelHandler,也可以利用netty给我们提供的channelHandler。连接被创建之后,就会执行initChannel。该方法是一个回调方法。
TestHttpServerHandler实现
/*** 我们自己定义的处理器** @author 荀彧 2021/1/5*/
public class TestHttpServerHandler extends SimpleChannelInboundHandler {
/*** 这个是读取客户端发送来的请求,并且向客户端发送响应的function** @param ctx* @param msg* @throws Exception*/
@Override
protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
if (msg instanceof HttpRequest) {
HttpRequest httpRequest = (HttpRequest)msg;
System.out.println("请求路径是:"+ ctx.channel().remoteAddress());
System.out.println("请求的方法名是:" + httpRequest.method().name());
// 构造响应内容 ByteBuf content = Unpooled.copiedBuffer("Hello world", CharsetUtil.UTF_8);
// 构造响应 FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,
HttpResponseStatus.OK,
content);
response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());
// 返回给客户端 ctx.writeAndFlush(response);
}
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("channel active");
super.channelActive(ctx);
}
/*** 通道注册* @param ctx* @throws Exception*/
@Override
public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("channel register");
super.channelRegistered(ctx);
}
/*** 通道被添加* @param ctx* @throws Exception*/
@Override
public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
System.out.println("handler added");
super.handlerAdded(ctx);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
System.out.println("channel Inactive");
super.channelInactive(ctx);
}
@Override
public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
System.out.println("channel Unregistered");
super.channelUnregistered(ctx);
}
}
完成了上述工作之后,我们启动TestServer。使用curl发送http请求,得到如下结果:
其中根据服务器控制台的输出如下:
handler added
channel register
channel active
请求路径是:/0:0:0:0:0:0:0:1:65095
请求的方法名是:GET
channel Inactive
channel Unregistered
我们重写了那几个方法,主要是为了看SimpleChannelInboundHandler中的调用链。
至此,我们已经利用netty完成了一个简单的http服务器,后续我们会对其中涉及到的api进行详细的分析,欢迎大家关注专栏,我们一起学习netty。uestc_wb/netty_learngitee.com
本节代码 firstexample