一、前言

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)

我们启动主服务类,然后用网络调试工具连接。

Netty的认识_netty

我们发送16进制(HEX)的数据。

Netty的认识_netty_02

在控制台日志也接收到了客户端传输过来的数据并转成字节数组。

我们通过进制转换工具查看转换后的数据是否一致。

Netty的认识_netty_03

Netty的认识_netty_04

09:31:55.625 [nioEventLoopGroup-3-1] INFO com.example.nettydemo.netty.NettyHandler - 接收到消息:[0, 17]