Netty入门——springboot框架开发一个简单的服务器端和客户端

Posted 小志的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Netty入门——springboot框架开发一个简单的服务器端和客户端相关的知识,希望对你有一定的参考价值。

目录

一、加入依赖

  • 加入依赖

    <dependency>
        <groupId>io.netty</groupId>
        <artifactId>netty-all</artifactId>
        <version>4.1.39.Final</version>
    </dependency>
    

二、服务器端

2.1、服务器端代码

  • 服务器端代码

    package com.example.nettytest.netty.day1;
    
    import io.netty.bootstrap.ServerBootstrap;
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.ChannelInboundHandlerAdapter;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.nio.NioserverSocketChannel;
    import io.netty.channel.socket.nio.NioSocketChannel;
    import io.netty.handler.codec.string.StringDecoder;
    import io.netty.handler.logging.LoggingHandler;
    
    /**
     * @description:
     * @author: xz
     */
    public class Server 
        public static void main(String[] args) 
            //1、服务端启动器:负责组装netty组件
            new ServerBootstrap()
                //2、添加 EventLoop(事件循环)
                .group(new NioEventLoopGroup())
                //3、选择服务器的 ServerSocketChannel 实现
                .channel(NioServerSocketChannel.class)
                //4、添加服务端处理器
                // boss负责处理连接;worker(也就是netty中的child) 负责处理读写,决定了 worker(也就是netty中的child) 能执行哪些操作(handler)
                .childHandler(
                        // 5. channel 代表和客户端进行数据读写的通道 Initializer 初始化,负责添加别的 handler
                        new ChannelInitializer<NioSocketChannel>() 
                        @Override
                        protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception 
                            //6、添加具体 handler
                            nioSocketChannel.pipeline().addLast(new LoggingHandler());
                            nioSocketChannel.pipeline().addLast(new StringDecoder());//将 ByteBuf 转换为字符串
                            nioSocketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter()//自定义handler
                                //处理读事件
                                @Override
                                public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception 
                                    // 打印上一步转换好的字符串
                                    System.out.println("msg==========="+msg);
                                
                            );
                        
                )
                //7、绑定监听端口
                .bind(8080);
        
    
    

2.2、服务器端代码解读

  • 代码1位置 :服务端启动器:负责组装netty组件

  • 代码2位置 :创建 NioEventLoopGroup,可以简单理解为 线程池 + Selector 后面会详细展开;

  • 代码3位置:选择服务 Scoket 实现类,其中 NioServerSocketChannel 表示基于 NIO 的服务器端实现,其它实现还有

  • 代码4位置:为啥方法叫 childHandler,是接下来添加的处理器都是给 SocketChannel 用的,而不是给 ServerSocketChannel。ChannelInitializer 处理器(仅执行一次),它的作用是待客户端 SocketChannel 建立连接后,执行 initChannel 以便添加更多的处理器;

  • 代码5位置:channel代表和客户端进行数据读写的通道 Initializer 初始化,负责添加别的 handler;

  • 代码6位置:添加具体 handler;

  • 代码7位置: ServerSocketChannel 绑定的监听端口;

三、客户端

3.1、客户端代码

  • 客户端代码
package com.example.nettytest.netty.day1;

import io.netty.bootstrap.Bootstrap;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

import java.net.InetSocketAddress;

/**
 * @description:
 * @author: xz
 */
public class Client 
    public static void main(String[] args) throws InterruptedException 
        // 1. 客户端启动器
        new Bootstrap()
            // 2. 添加 EventLoop(事件循环)
            .group(new NioEventLoopGroup())
            // 3. 选择客户端的 SocketChannel 实现
            .channel(NioSocketChannel.class)
            // 4. 添加客户端处理器
            .handler(new ChannelInitializer<NioSocketChannel>() 
                // 在连接建立后被调用
                @Override
                protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception 
                    //9. 消息会经过通道 handler 处理,这里是将 String => ByteBuf 发出
                    nioSocketChannel.pipeline().addLast(new StringEncoder());
                
            )
            .connect(new InetSocketAddress("localhost",8080))//5. 连接到服务器
            .sync()//6. 等待 connect 建立连接完毕
            .channel()//7. 连接对象
            .writeAndFlush("hello world !");//8. 发送数据
    

3.2、客户端代码解读

  • 代码1位置 :客户端启动器;
  • 代码2位置 :创建 NioEventLoopGroup(事件循环),同 Server服务端;
  • 代码3位置 :选择客户 Socket 实现类,NioSocketChannel 表示基于 NIO 的客户端实现,其它实现还有
  • 代码4位置 :添加 SocketChannel 的处理器,ChannelInitializer 处理器(仅执行一次),它的作用是待客户端 SocketChannel 建立连接后,执行 initChannel 以便添加更多的处理器;
  • 代码5位置 :指定要连接的服务器和端口;
  • 代码6位置 :Netty 中很多方法都是异步的,如 connect,这时需要使用 sync 方法等待 connect 建立连接完毕;
  • 代码7位置 :获取 channel 对象,它即为通道抽象,可以进行数据读写操作;
  • 代码8位置 :入消息并清空缓冲区;
  • 代码9位置 :消息会经过通道 handler 处理,这里是将 String => ByteBuf 发出;
    数据经过网络传输,到达服务器端,服务器端 5 和 6 处的 handler 先后被触发,走完一个流程

四、服务端和客户端流程梳理

  • 流程梳理

五、channel 、msg 、handler 和eventLoop 概念理解

5.1、channel 的理解

  • 把 channel 理解为数据的通道

5.2、msg 的理解

  • 把 msg 理解为流动的数据,最开始输入是 ByteBuf,但经过 pipeline 的加工,会变成其它类型对象,最后输出又变成 ByteBuf

5.3、handler 的理解

  • 把 handler 理解为数据的处理工序
    (1)、工序有多道,合在一起就是 pipeline,pipeline 负责发布事件(读、读取完成…)传播给每个 handler, handler 对自己感兴趣的事件进行处理(重写了相应事件处理方法);
    (2)、handler 分 Inbound 和 Outbound 两类;

5.4、eventLoop 的理解

  • 把 eventLoop 理解为处理数据的工人
    (1)、工人可以管理多个 channel 的 io 操作,并且一旦工人负责了某个 channel,就要负责到底(绑定);
    (2)、工人既可以执行 io 操作,也可以进行任务处理,每位工人有任务队列,队列里可以堆放多个 channel 的待处理任务,任务分为普通任务、定时任务;
    (3)、工人按照 pipeline 顺序,依次按照 handler 的规划(代码)处理数据,可以为每道工序指定不同的工人;

以上是关于Netty入门——springboot框架开发一个简单的服务器端和客户端的主要内容,如果未能解决你的问题,请参考以下文章

网络应用框架Netty快速入门

springboot netty非阻塞协议搭建

网络开发的最强大框架:Netty快速入门

网络开发的最强大框架:Netty快速入门

Netty入门看这一篇就够了

Netty入门