Netty快速入门(一)

Netty简介

Netty是由jboss提供的一个基于NIO的开源框架。Netty提供异步、基于事件驱动的网络应用程序框架,用于快速开发出高性能、高可靠性的网络IO程序。

Netty模型

在这里插入图片描述

上图文解:
1.Netty需要创建两组线程池(NioEventLoopGroup),BossGroup主要负责客户端的请求连接,连接成功后BossGroup会把连接交给 Worker Group,Worker Group负责客户端的读写操作。
2.NioEventLoopGroup可以看作是一个事件循环组,这个组中有多个事件循环,每一个循环事件都是NioEventLoop
3.NioEventLoop不断地循环执行处理任务的线程,每一个NioEventLoop都有一个selector,用于监听绑定在其上的Socket网络通讯
4.NioEventLoopGroup里面包含多个NioEventLoop
5.每个Boss EventLoopGroup循环执行的步骤有三步:
1)轮询客户端access(连接)事件
2)处理access事件,建立连接后生成NioSocketChannel,并注册到某个Worker NioEventLoop上的selector
3)处理任务队列中的任务runAllTasks
6.每个Worker NioEventLoopGroup循环执行的步骤:
1)轮询read/write(读/写)事件
2)在对应的NioSocketChannel中处理读写事件
3)处理任务队列的任务runAllTasks
7.每个worker EventLoop处理业务时,会使用pipeline(管道) ,pipeline中包含了channel,可以获取到对应通道,并维护了很多的处理器

Netty快速入门小案例

案例要求
1)Netty服务器监听6668端口,客户端能发送消息给服务器 " 你好,服务器"
2)服务器回复消息给客户端 "你好,客户端"

导入maven

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

服务器端代码

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

/**
 * 入门小案例
 * 代码会在后面详解
 * */
public class NettyServer1 {
    public static void main(String[] args) {
        //创建bossGroup和workGroup
        //构造函数设置为1个线程运行bossGroup
        EventLoopGroup boss = new NioEventLoopGroup(1);
        //构造函数为空默认为当前Cpu核心数*2个线程
        EventLoopGroup worker = new NioEventLoopGroup();
        try{
            //serverBootStrap可以理解为用于构建服务器端的核心组件
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(boss,worker)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            //获取到pipeline
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            //增加编解码器
                            pipeline.addLast(new StringEncoder());
                            pipeline.addLast(new StringDecoder());
                            //增加自己定义的handler,用于接收客户端发送的信息
                            pipeline.addLast(new NettyServerHandler());
                        }
                    });
            //绑定端口号并开启服务
            ChannelFuture future = serverBootstrap.bind(6668).sync();
            //这段代码是阻塞的,并不会立即执行,直到服务器关闭后优雅的退出
            future.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //优雅的关闭boss和worker(处理完所有请求后会关闭)
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }
    }
}
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
/**
 * 因为Netty是基于事件处理的
 * 所以该类用于读写连接等事件处理的,每一种事件都有不用的处理方法,继承SimpleChannelInboundHandler,泛型为接收的数据类型
 * */
public class NettyServerHandler extends SimpleChannelInboundHandler<String> {
    /**
     * 读取客户端发送的数据
     * */
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
        System.out.println("服务器端接收到数据:"+" "+s);
        //获取到channel用于回复客户端
        Channel channel = channelHandlerContext.channel();
        channel.writeAndFlush("你好,客户端");
    }
    /**
     * 发生异常后,关闭客户端连接
     * */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}

客户端代码

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

/**
 * 客户端代码
 * */
public class NettyClient1 {
    public static void main(String[] args) {
        //客户端不需要多个eventLoopGroup
        EventLoopGroup group = new NioEventLoopGroup();
        try{
            //bootStrap可以理解为构建客户端的核心组件,服务器端为serverBootStrap
            Bootstrap bootstrap = new Bootstrap();
            ChannelFuture future = bootstrap.group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            //增加编解码器
                            pipeline.addLast(new StringEncoder());
                            pipeline.addLast(new StringDecoder());
                            //增加自定义的handler
                            pipeline.addLast(new NettyClientHandler());
                        }
                        //创建连接
                    }).connect("127.0.0.1", 6668).sync();
            future.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            //优雅的关闭
            group.shutdownGracefully();
        }
    }
}
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

public class NettyClientHandler extends SimpleChannelInboundHandler<String> {
    /**
     * 读取服务器返回的消息
     * */
    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
        System.out.println("接收到服务器消息"+" "+s);
    }
    /**
     * 建立连接后发送信息给服务器
     * */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.channel().writeAndFlush("你好,服务器");
    }
}

实现效果
在这里插入图片描述
在这里插入图片描述
入门案例就完成了,代码会在后面Netty快速入门(四)进行讲解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值