概述
Netty是由JBOSS提供的一个Java开源框架。Netty提供异步的、基于事件驱动的网络应用程序框架,用以快速开发高性能、高可靠的网络IO程序 Netty可以帮助你快速、简单的开发出一个网络应用,相当于简化和流程化了NIO的开发过程 Netty是目前最流行的NIO框架,Netty在互联网领域,大数据分布式计算领域、游戏行业、通信行业等获得了广泛的应用,知名的ElasticSearch、Dobbo框架内不都采用了Netty
服务器端
package com. zhj. netty1 ;
import io. netty. bootstrap. ServerBootstrap ;
import io. netty. channel. ChannelFuture ;
import io. netty. channel. ChannelInitializer ;
import io. netty. channel. ChannelOption ;
import io. netty. channel. EventLoopGroup ;
import io. netty. channel. nio. NioEventLoopGroup ;
import io. netty. channel. socket. SocketChannel ;
import io. netty. channel. socket. nio. NioServerSocketChannel ;
import io. netty. channel. socket. nio. NioSocketChannel ;
public class NettyServer {
public static void main ( String [ ] args) throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup ( ) ;
EventLoopGroup workerGroup = new NioEventLoopGroup ( ) ;
try {
ServerBootstrap bootstrap = new ServerBootstrap ( ) ;
bootstrap. group ( bossGroup, workerGroup)
. channel ( NioServerSocketChannel . class )
. option ( ChannelOption . SO_BACKLOG, 128 )
. childOption ( ChannelOption . SO_KEEPALIVE, true )
. childHandler ( new ChannelInitializer < SocketChannel > ( ) {
@Override
protected void initChannel ( SocketChannel ch) throws Exception {
ch. pipeline ( ) . addLast ( new NettyServerHandler ( ) ) ;
}
} ) ;
System . out. println ( "服务器 is ready 。。。" ) ;
ChannelFuture cf = bootstrap. bind ( 6668 ) . sync ( ) ;
cf. channel ( ) . closeFuture ( ) . sync ( ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
} finally {
bossGroup. shutdownGracefully ( ) ;
workerGroup. shutdownGracefully ( ) ;
}
}
}
package com. zhj. netty1 ;
import io. netty. buffer. ByteBuf ;
import io. netty. buffer. Unpooled ;
import io. netty. channel. ChannelHandlerContext ;
import io. netty. channel. ChannelInboundHandlerAdapter ;
import io. netty. util. CharsetUtil ;
import java. nio. ByteBuffer ;
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead ( ChannelHandlerContext ctx, Object msg) throws Exception {
System . out. println ( "server ctx=" + ctx) ;
ByteBuf buf = ( ByteBuf ) msg;
System . out. println ( "客户端发送的消息是:" + buf. toString ( CharsetUtil . UTF_8) ) ;
System . out. println ( "客户端地址是:" + ctx. channel ( ) . remoteAddress ( ) ) ;
}
@Override
public void channelReadComplete ( ChannelHandlerContext ctx) throws Exception {
ctx. writeAndFlush ( Unpooled . copiedBuffer ( "hello,客户端" , CharsetUtil . UTF_8) ) ;
}
@Override
public void exceptionCaught ( ChannelHandlerContext ctx, Throwable cause) throws Exception {
ctx. close ( ) ;
}
}
客户端
package com. zhj. netty1 ;
import io. netty. bootstrap. Bootstrap ;
import io. netty. channel. ChannelFuture ;
import io. netty. channel. ChannelInitializer ;
import io. netty. channel. nio. NioEventLoopGroup ;
import io. netty. channel. socket. SocketChannel ;
import io. netty. channel. socket. nio. NioSocketChannel ;
public class NettyClient {
public static void main ( String [ ] args) {
NioEventLoopGroup group = new NioEventLoopGroup ( ) ;
try {
Bootstrap bootstrap = new Bootstrap ( ) ;
bootstrap. group ( group)
. channel ( NioSocketChannel . class )
. handler ( new ChannelInitializer < SocketChannel > ( ) {
@Override
protected void initChannel ( SocketChannel ch) throws Exception {
ch. pipeline ( ) . addLast ( new NettyClientHandler ( ) ) ;
}
} ) ;
System . out. println ( "客户端 ok" ) ;
ChannelFuture channelFuture = bootstrap. connect ( "127.0.0.1" , 6668 ) . sync ( ) ;
channelFuture. channel ( ) . closeFuture ( ) . sync ( ) ;
} catch ( Exception e) {
e. printStackTrace ( ) ;
} finally {
group. shutdownGracefully ( ) ;
}
}
}
package com. zhj. netty1 ;
import io. netty. buffer. ByteBuf ;
import io. netty. buffer. Unpooled ;
import io. netty. channel. ChannelHandlerContext ;
import io. netty. channel. ChannelInboundHandlerAdapter ;
import io. netty. util. CharsetUtil ;
public class NettyClientHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelActive ( ChannelHandlerContext ctx) throws Exception {
System . out. println ( "client" + ctx) ;
ctx. writeAndFlush ( Unpooled . copiedBuffer ( "hello,server:🐱" , CharsetUtil . UTF_8) ) ;
}
@Override
public void channelRead ( ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf buf = ( ByteBuf ) msg;
System . out. println ( "服务器回复的消息" + buf. toString ( CharsetUtil . UTF_8) ) ;
System . out. println ( "服务器的地址" + ctx. channel ( ) . remoteAddress ( ) ) ;
}
@Override
public void exceptionCaught ( ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause. printStackTrace ( ) ;
ctx. close ( ) ;
}
}
解读
Netty抽象出了两组线程池BossGroup专门负责接收客户端的连接,WorkerGroup专门负责网络的读写 BossGroup和WorkerGroup类型都是NioEventLoopGroup NioEventLoopGroup相当于一个事件循环组,这个组中含有多个事件循环,每个事件循环时NioEventLoop NioEventLoop表示一个不断循环执行处理的任务的线程,每个NioEventLoop都有一个Selector,用于监听绑定在其上的socket的网络通讯 NioEventLoopGroup可以有多个线程,既可以含有多个NioEventLoop 每个BossNioEventLoop 循环执行的步骤有3步 a. 轮询accept事件 b. 处理accept事件,与client建立连接,生成NioSocketChannel,并将其注册到某个worker NIOEventLoop上的selector c. 处理任务队列的任务,即runAllTasks 每个WorkerNioEventLoop 循环执行的步骤 a. 轮询read,write事件 b. 处理Io事件,即read,write事件,在对应NioSocketChannel处理 c. 处理任务对立的任务,即runAllTask 每个Worker NioEventLoop处理业务时,会使用pipline(管道),pipeline中包含了channel,即通过pepeline可以获取到对应通道,