1.Netty支持三种IO模型同时支持三种Reactor模式。
2.Netty支持很多应用层的协议,提供了很多decoder和encoder。
3.Netty能够解决TCP长连接所带来的缺陷(粘包、半包等)
4.Netty支持应用层的KeepAlive。
5.Netty规避了JAVA NIO中的很多BUG,性能更好。
Netty启动服务端1.创建ServerBootstrap服务端启动对象。
2.配置bossGroup和workerGroup,其中bossGroup负责接收连接,workerGroup负责处理连接的读写就绪事件。
3.配置父Channel,一般为NioServerSocketChannel。
4.配置子Channel与Handler之间的关系。
5.给父Channel配置参数。
6.给子Channel配置参数。
7.绑定端口,启动服务。
private void start() { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); ServerBootstrap serverBootstrap = new ServerBootstrap(); serverBootstrap .group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) // 配置父Channel .childHandler(new ChannelInitializer<SocketChannel>() { // 配置子Channel与Handler之间的关系 @Override protected void initChannel(SocketChannel socketChannel) { // 往ChannelPipeline中添加ChannelHandler socketChannel.pipeline().addLast( new HttpRequestDecoder(), new HttpObjectAggregator(65535), new HttpResponseEncoder(), new HttpServerHandler() ); } }) .option(ChannelOption.SO_BACKLOG, 128) // 给父Channel配置参数 .childOption(ChannelOption.SO_KEEPALIVE, true); // 给子Channel配置参数 try { // 绑定端口,启动服务 System.out.println("start server and bind 8888 port ..."); serverBootstrap.bind(8888).sync(); } catch (InterruptedException e) { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } Netty启动客户端1.创建Bootstrap客户端启动对象。
2.配置workerGroup,负责处理连接的读写就绪事件。
3.配置父Channel,一般为NioSocketChannel。
4.给父Channel配置参数。
5.配置父Channel与Handler之间的关系。
6.连接服务器。
private void start() { EventLoopGroup workerGroup = new NioEventLoopGroup(); Bootstrap bootstrap = new Bootstrap(); bootstrap.group(workerGroup) .channel(NioSocketChannel.class) // 配置父Channel .option(ChannelOption.SO_KEEPALIVE, true) // 给父Channel配置参数 .handler(new ChannelInitializer<SocketChannel>() { // 配置父Channel与Handler之间的关系 @Override protected void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast(new TimeClientHandler()); } }); try { bootstrap.connect(new InetSocketAddress(8888)).sync(); // 连接服务器 } catch (InterruptedException e) { workerGroup.shutdownGracefully(); } } ChannelInBoundHandler接口声明了事件的处理方法 channelActive():当建立一个新的Channel时调用该方法 handlerAdd():当往Channel的ChannelPipeline中添加Handler时调用该方法 handlerRemove():当移除ChannelPipeline中的Handler时调用该方法 channelRead():当Channel有数据可读时调用该方法 exceptionCaught():当在处理事件发生异常时调用该方法ServerSocketChannel每接收到一个新的连接时都会建立一个SocketChannel,然后调用ChannelInitializer的init方法初始化Channel,方法中配置Channel与Handler之间的关系,然后调用Handler的handlerAdd()和channelActive()方法。
关于ChannelPipelineChannelPipeline底层使用双向链表。
当Channel有数据可读时,会沿着链表从前往后寻找有IN性质的Handler进行处理。
当Channel写入数据时,会沿着链表从后往前寻找有OUT性质的Handler进行处理。
关于write()和flush()方法graph TB; S1[Channel的write方法] --将数据写入到缓冲区--> buffer[缓冲区]; S2[Channel的flush方法] --发送缓冲区中的数据并清空--> buffer[缓冲区]; buffer --发送--> S3[SocketChannel];