Netty网络框架

Netty是一个异步的基于事件驱动的网络框架

为什么要使用Netty而不直接使用JAVA中的NIO

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()方法。

关于ChannelPipeline

ChannelPipeline底层使用双向链表。

Netty网络框架

当Channel有数据可读时,会沿着链表从前往后寻找有IN性质的Handler进行处理。

当Channel写入数据时,会沿着链表从后往前寻找有OUT性质的Handler进行处理。

关于write()和flush()方法

graph TB; S1[Channel的write方法] --将数据写入到缓冲区--> buffer[缓冲区]; S2[Channel的flush方法] --发送缓冲区中的数据并清空--> buffer[缓冲区]; buffer --发送--> S3[SocketChannel];

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsswdd.html