1、什么是Netty
Netty 是一个异步的(基于多路复用的)、基于事件驱动的网络应用框架,用于快速开发可维护、高性能的网络服务器和客户端
2、Netty的优势
如果使用传统NIO,其工作量大,bug 多
- 需要自己构建协议
- 解决 TCP 传输问题,如粘包、半包
- 因为bug的存在,epoll 空轮询导致 CPU 100%
Netty 对 API 进行增强,使之更易用,如
- FastThreadLocal => ThreadLocal
- ByteBuf => ByteBuffer
二、入门案例
1、服务器端代码
1、ServerBootstrap启动器,负责装配netty组件,启动服务器:
1.1)创建线程池
1.2)选择服务器的 ServerSocketChannel 实现,这里为nio
1.3)指定子处理器:StringDecoder解码,ByteBuf=>String。。。。。。
1.4)绑定8080端口
// 1、ServerBootstrap启动器,负责装配netty组件,启动服务器:
1.1)创建线程池
1.2)选择服务器的 ServerSocketChannel 实现,这里为nio
1.3)指定子处理器:StringDecoder解码,ByteBuf=>String。。。。。。
1.4)绑定8080端口
public class HelloServer {
public static void main(String[] args) {
// 1、启动器,负责装配netty组件,启动服务器
new ServerBootstrap()
// 2、创建 NioEventLoopGroup,可以简单理解为 线程池 + Selector
.group(new NioEventLoopGroup())
// 3、选择服务器的 ServerSocketChannel 实现
.channel(NioServerSocketChannel.class)
// 4、child 负责处理读写,该方法决定了 child 执行哪些操作
// ChannelInitializer 处理器(仅执行一次)
// 它的作用是待客户端SocketChannel建立连接后,执行initChannel以便添加更多的处理器
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
// 5、SocketChannel的处理器,使用StringDecoder解码,ByteBuf=>String
nioSocketChannel.pipeline().addLast(new StringDecoder());
// 6、SocketChannel的业务处理,使用上一个处理器的处理结果
nioSocketChannel.pipeline().addLast(new SimpleChannelInboundHandler<String>() {
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
System.out.println(s);
}
});
}
// 7、ServerSocketChannel绑定8080端口
}).bind(8080);
}
}
2、客户端代码
// 2、ServerBootstrap启动器,负责装配netty组件,启动服务器:
1.1)创建线程池
1.2)选择服务器的 ServerSocketChannel 实现,这里为nio
1.3)指定子处理器,以待客户端SocketChannel建立连接后,执行initChannel以便添加更多的处理器
1.4)指定要连接的服务器和端口:connect(new InetSocketAddress("", ))
1.5)使用 sync 方法等待 connect 建立连接完毕
1.6)获取 channel 对象,以进行数据读写操作
public class HelloClient {
public static void main(String[] args) throws InterruptedException {
new Bootstrap()
.group(new NioEventLoopGroup())
// 选择客户 Socket 实现类,NioSocketChannel 表示基于 NIO 的客户端实现
.channel(NioSocketChannel.class)
// ChannelInitializer 处理器(仅执行一次)
// 它的作用是待客户端SocketChannel建立连接后,执行initChannel以便添加更多的处理器
.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) throws Exception {
// 消息会经过通道 handler 处理,这里是将 String => ByteBuf 编码发出
channel.pipeline().addLast(new StringEncoder());
}
})
// 指定要连接的服务器和端口
.connect(new InetSocketAddress("localhost", 8080))
// Netty 中很多方法都是异步的,如 connect
// 这时需要使用 sync 方法等待 connect 建立连接完毕
.sync()
// 获取 channel 对象,它即为通道抽象,可以进行数据读写操作
.channel()
// 写入消息并清空缓冲区
.writeAndFlush("hello world");
}
}