Netty是基于CS架构的一种模式,分为Client端和Server端
(1)先从Server端开始,先看一下Netty服务端的运行原理图:
首先你得知道下面的几个主要的角色:
- serverBootstrap
- NioEventLoopGroup (这个是专门负责接收client端的请求的)
- NioEventLoopGroup (这个是专门负责干活的)
- NioServerSocketChannel (当和client建立连接之后,生成NioSocketChannel,并将NioSocketChannel注册到某个worker NioEventLoop的selector上)
然后就是具体的执行Netty服务端的具体执行流程:
- 首先server端启动时绑定本地某个端口,初始化channel,其实就是生成channel的实例对象NioServerSocketChannel。
- 然后将自己NioServerSocketChannel注册到某个bossGroup(其实就是让前台经理先去接待)的NioEventLoop的selector上,每个NioEventLoop包含1个selector和1个事件循环线程
- 然后进入到bossGroup的循环线程中,其实就是他要怎么去处理这个“接待”的过程
- 第一步bossGroup需要去轮询accept事件,
- 第二步就是去处理IO事件,然后和client建立连接,生成NioSocketChannel,并将NioSocketChannel注册到某个workerGroup NioEventLoop的selector上
- 第三步处理任务队列中的任务,runAllTasks。任务队列中的任务包括用户调用eventloop.execute或schedule执行的任务,或者其它线程提交到该eventloop的任务
- 完事之后任务就开始进入到了wrokGroup线程组中来去真正的干活了,因为他也是一个线程组
- 第一步是先轮询read、write事件
- 第二步就开始处理io任务,即read、write事件,在NioSocketChannel可读、可写事件发生时进行处理
- 第三步还是处理任务队列中的任务,runAllTasks
这是Netty服务端的基本使用的模板代码:
public class NettyServer {
public static void main(String[] args) throws InterruptedException {
//可以把这个看成是一个大Boss负责把这个公司的环境给搭建好,把人员给各就各位
ServerBootstrap serverBootstrap = new ServerBootstrap();
//这个相当于前台经理Boss(主要负责接待),这个组里包含多个事件循环,每个NioEventLoop包含1个selector和1个事件循环线程
NioEventLoopGroup boosGroup = new NioEventLoopGroup();
//这个就是worker线程组,相当于技术经理主要负责产出
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
//这个其实就是绑定端口,初始化各种组件
try {
ChannelFuture channelFuture = serverBootstrap
//前者是一个父线程池事件组,后者参数是子线程池事件组(其实就是专门用来处理具体的任务的)
.group(boosGroup, workerGroup)
//指定 Channel 的类型. 因为是服务器端, 因此使用了 NioServerSocketChannel.
.channel(NioServerSocketChannel.class)
//设置数据的处理器.
.childHandler(new ChannelInitializer<NioSocketChannel>() {
@Override
protected void initChannel(NioSocketChannel ch) {
ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new SimpleChannelInboundHandler<String>() {
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) {
System.out.println("打印管道中的信息----->" + msg);
}
});
}
})
.bind(9090).sync();
}finally {
//这里是关闭线程组
boosGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
(2)然后是Client端的clientServer的代码,看一下他的原理运行图:
ClientServer端的运行原理流程:
- 首先ClientServer端也是需要去进行一些初始化,然后通过connect()方法去绑定服务器端的ip地址和端口,然后也需要去初始化channel的实例对象NioSocketChannel,和Server端差不多,但是不同的是ClientServer端只需要一个线程事件组就可以了,NioEventLoop也是需要三步来完成.
- 第一步轮询connect、read、write事件;
- 第二步处理io任务,即connect、read、write事件,在NioSocketChannel连接建立、可读、可写事件发生时进行处理
- 第三步:处理非io任务,runAllTasks
ClientServer端的代码模板:
public class NettyClient {
public static void main(String[] args) throws InterruptedException {
Bootstrap bootstrap = new Bootstrap();
//这里是定义一个事件组,其实本质就是他的父类MultithreadEventExecutorGroup维护了一个线程池 EventExecutor children
NioEventLoopGroup group = new NioEventLoopGroup();
bootstrap.group(group)
//指定 Channel 的类型. 因为是客户端, 因此使用了NioSocketChannel. Channel 是通过工厂方法 ChannelFactory.newChannel()
.channel(NioSocketChannel.class)
//设置数据的处理器.
.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) {
ch.pipeline().addLast(new StringEncoder());
}
});
//连接服务器地址和端口并且绑定通道
Channel channel = bootstrap.connect("127.0.0.1", 9090).channel();
while (true) {
channel.writeAndFlush(new Date() + ": hello world!");
channel.write("客户端向服务器中的管道中写入数据------>");
Thread.sleep(2000);
}
}
}
Netty的NIO模型: