一、前言
Netty是JBOSS开源的一款NIO网络编程框架,可用于快速开发网络的应用。Netty是一个异步的、基于事件驱动的网络应用框架,用于快速开发高性能的服务端和客户端。可以极大的简化基于TCP、UDP等协议的网络服务。并且Netty对于各种传输类型、通讯方式(HTTP或websocket)都提供了统一的API接口,提供了灵活的可扩展性,高度可自定义的线程模型,支持使用无连接的数据报UDP进行通信,具有高吞吐量、低延迟、资源消耗低、最低限度内存复制等特性。除了优越的性能外,Netty还支持SSL/TLS和StartTLS等加密传输协议,保证了数据传输的安全性。
二、Netty组成
Netty做为一个Web服务器,通常包含以下几个部分:
1.主服务类
通过ServerBootstrap注册serverGroup和clientGroup两个事件循环组,其中serverGroup用于获取服务端连接,clientGroup用于处理客户端连接。
2.初始化器
Netty封装了各种各样的内置处理器,在初始化器中根据业务需求选择Netty的内置处理器。
3.自定义消息处理器
接收客户端的所有请求,并作出响应。
简单讲,Netty程序就是通过主服务类关联自定义初始化器,然后在初始化器中加入Netty内置处理器和自定义处理器,最后在自定义处理器中编写处理特定需求的业务代码。
三、代码实例
1.引入依赖
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</dependency>
2.主服务类
package com.example.nettydemo.netty;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/**
* @author qx
* @date 2023/12/29
* @des Netty服务
*/
public class NettyServer {
public static void main(String[] args) {
// 用户监听及建立连接,并把每一个连接抽象成一个channel,最后将连接交给clientGroup处理
EventLoopGroup serverGroup = new NioEventLoopGroup();
EventLoopGroup clientGroup = new NioEventLoopGroup();
// 服务端启动时初始化操作
ServerBootstrap serverBootstrap = new ServerBootstrap();
// 将serverGroup和clientGroup注册到服务端的Channel上,注册一个服务端初始化器,初始化器中的initChannel()方法会在连接被注册到Channel后立即执行
serverBootstrap.group(serverGroup, clientGroup).channel(NioServerSocketChannel.class).childHandler(new NettyInitializer()).bind(8888);
}
}
3.初始化器
package com.example.nettydemo.netty;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.bytes.ByteArrayDecoder;
import io.netty.handler.codec.bytes.ByteArrayEncoder;
/**
* @author qx
* @date 2023/12/29
* @des Netty初始化器
*/
public class NettyInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
// 添加字节数组的解码器
pipeline.addLast(new ByteArrayDecoder());
pipeline.addLast(new ByteArrayEncoder());
// 添加自定义处理器
pipeline.addLast("handler", new NettyHandler());
}
}
4.自定义处理器
package com.example.nettydemo.netty;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
/**
* @author qx
* @date 2023/12/29
* @des Netty自定义处理器
*/
@Slf4j
public class NettyHandler extends SimpleChannelInboundHandler<Object> {
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {
byte[] bytes = (byte[]) o;
log.info("接收到消息:{}", Arrays.toString(bytes));
}
}
四、测试
我们可以下载Windows下的网络调试工具NetAssist,它对于需要编写各种通信协议的TCP服务端、客户端以及UDP通信程序来说是很方便的。
NetAssist的下载地址为: NetAssist.exe( http://www.cmsoft.cn/download/cmsoft/netassist.zip)
我们启动主服务类,然后用网络调试工具连接。
我们发送16进制(HEX)的数据。
在控制台日志也接收到了客户端传输过来的数据并转成字节数组。
我们通过进制转换工具查看转换后的数据是否一致。
09:31:55.625 [nioEventLoopGroup-3-1] INFO com.example.nettydemo.netty.NettyHandler - 接收到消息:[0, 17]