Netty (一)实现简单通讯

一、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来实现的简单的一个通讯,谢谢

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JokerQGA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值