一、Netty中的重要组件
1、Bootstrap / ServerBootstrap (建立连接):
Netty引导组件,简化NIO的开发步骤,是一个Netty程序的开始,作用是配置和串联各个组件
2、EventLoopGroup (事件循环组) :
是EventLoop组合,可以包含多个EventLoop。创建一个EventLoopGroup的时候,内部包含的方法就会创建一个子对象EventLoop
3、EventLoop (事件循环):
循环服务Channel,可以包含多个Channel
4、Channel (通道):
代表一个Socket连接,或者其他IO操作组件。Channel是通讯的载体
5、ChannelInitializer (初始化连接):
主要提供了一个传输通道ChannelPipeline
6、ChannelPipeline (传输通道):
主要是管理各种ChannelHandler业务控制器,提供一个链式管理模式
7、ChannelHandler (业务控制器):
主要业务写入,Netty也提供了很多写好的控制器和适配器,可以直接引用
8、ChannelInBoundHandler (通道传入控制器):
继承至ChannelHandler,在传输通道中对传入事件进行控制
9、ChannelOutBoundHandler (通道传出控制器):
继承至ChannelHandler,在传输通道中对传出事件进行控制
10、Decoder (解码):
网络传输都是byte传输,所以Netty首先接收的是byte,需要进行解码,编程Java对象。Netty提供了很多解码器
11、Encoder (编码):
和解码类似,在传入服务器的时候,需要编码成byte传输给客户端
12、Future / ChannelFuture (消息返回) :
Netty提供的返回结果,类似回调函数,告知你执行结果
二、Netty线程模型
1、单线程模型
指的是所有的IO操作都在同一个NIO线程上面完成,一个线程既要处理客户端连接还要处理客户端的读写操作
2、多线程模型
多线程模型与单线程模型最大的区别就是一组NIO线程处理O操作
3、主从线程模型
服务端有两个线程池,主线程主要处理客户端的连接,从线程主要处理客户端的读写
进入主题----Netty实现通讯
<!-- 引入依赖 -->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-codec-http</artifactId>
<version>4.1.45.Final</version>
</dependency>
编写服务端
/**
* @Author Joker
* @Date 2020/11/12
* @since 1.8
*/
public class Server1 {
public static void main(String[] args) {
// 创建主从线程池
EventLoopGroup masterEventLoopGroup = new NioEventLoopGroup();
EventLoopGroup slaveEventLoopGroup = new NioEventLoopGroup();
try {
// 创建服务的启动类
ServerBootstrap bootstrap = new ServerBootstrap();
// 设置Netty的主从线程模式
bootstrap.group(masterEventLoopGroup, slaveEventLoopGroup);
// 设置Netty管道类型
bootstrap.channel(NioServerSocketChannel.class);
// 设置客户端消息处理对象
bootstrap.childHandler(new ServerChannelHandler());
// 设置绑定端口,端口绑定是一个异步操作,所以下面需要阻塞
ChannelFuture bind = bootstrap.bind(8888);
// 阻塞当前线程,端口绑定成功后往下执行
bind.sync();
System.out.println("端口绑定成功");
// 等待通道被关闭
bind.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 关闭
masterEventLoopGroup.shutdownGracefully();
slaveEventLoopGroup.shutdownGracefully();
}
}
}
创建一个客户端消息处理对象
/**
* @Author Joker
* @Date 2020/11/12
* @since 1.8
*/
@ChannelHandler.Sharable
public class ServerChannelHandler extends SimpleChannelInboundHandler<ByteBuf> {
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception {
// 打印服务器接收到的消息
System.out.println("接收到客户端发送的消息:" + byteBuf.toString(Charset.defaultCharset()));
// 创建byteBuf 并给客户端返回消息
ByteBuf buffer = Unpooled.buffer(1024);
buffer.writeBytes(byteBuf);
buffer.writeBytes("服务器已接收消息".getBytes("utf-8"));
channelHandlerContext.writeAndFlush(buffer);
}
}
创建客户端
/**
* @Author Joker
* @Date 2020/11/12
* @since 1.8
*/
public class Client1 {
public static void main(String[] args) {
EventLoopGroup eventExecutors = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
// 设置多线程处理
bootstrap.group(eventExecutors);
// 设置客户端管道类型
bootstrap.channel(NioSocketChannel.class);
// 设置客户端处理类
bootstrap.handler(new SimpleChannelInboundHandler<ByteBuf>() {
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception {
System.out.println("客户端收到内容:" + byteBuf.toString(Charset.defaultCharset()));
}
});
// 连接服务器
ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 8888);
// 阻塞
channelFuture.sync();
System.out.println("连接成功...");
//
while (true) {
Scanner scanner = new Scanner(System.in);
String inp = scanner.nextLine();
// 获取客户端的通道给服务端发消息
Channel channel = channelFuture.channel();
// 创建ByteBuf
ByteBuf byteBuf = Unpooled.buffer(1024);
// 将内容写到byteBuf中
byteBuf.writeBytes(inp.getBytes("UTF-8"));
// 将buff写到管道中
channel.writeAndFlush(byteBuf);
}
} catch (InterruptedException | UnsupportedEncodingException e) {
e.printStackTrace();
} finally {
// 释放资源
eventExecutors.shutdownGracefully();
}
}
}
运行(可以多开几个客户端一起访问)
好了,这就是使用Netty来实现的简单的一个通讯,谢谢