Netty快速入门

Netty快速入门

异步非阻塞IO


什么是Netty

Netty 是一个基于 JAVA NIO 类库的异步通信框架,它的架构特点是:异步非阻塞、基于事件驱动、高性能、高可靠性和高可定制性。

Netty应用场景

1.分布式开源框架中dubbo、Zookeeper,RocketMQ,底层rpc通讯使用就是netty。
2.游戏开发中,底层使用netty通讯。

为什么选择netty

因为可以解决NIO代码复杂问题,以及有更好的容错机制!

那么为什么不建议开发者直接使用JDK的NIO类库进行开发?

1) NIO的类库和API繁杂,使用麻烦,你需要熟练掌握Selector、ServerSocketChannel、SocketChannel、ByteBuffer等;
2) 需要具备其它的额外技能做铺垫 。
例如:熟悉Java多线程编程,因为NIO编程涉及到Reactor模式,你必须对多线程和网路编程非常熟悉,才能编写出高质量的NIO程序;
3) 可靠性能力补齐,工作量和难度都非常大。
例如:客户端面临断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异常码流的处理等等,NIO编程的特点是功能开发相对容易,但是可靠性能力补齐工作量和难度都非常大;
4) JDK NIO的BUG。
例如:臭名昭著的epoll bug,它会导致Selector空轮询,最终导致CPU 100%。官方声称在JDK1.6版本的update18修复了该问题,但是直到JDK1.7版本该问题仍旧存在,只不过该bug发生概率降低了一些而已,它并没有被根本解决。

代码示例

Maven坐标
        <dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty</artifactId>
            <version>3.10.5.Final</version>
        </dependency>
Netty服务器端
public class NettyServer {
    public static void main(String[] args) {
        //创建服务类对象
        ServerBootstrap serverBootstrap = new ServerBootstrap();
        //创建两个线程池,分别为监听端口,监听NIO
        ExecutorService boos = Executors.newCachedThreadPool();
        ExecutorService worker = Executors.newCachedThreadPool();
        //设置工程,并把两个线程池加入其中
        serverBootstrap.setFactory(new NioServerSocketChannelFactory(boos,worker));
        //设置管道工程
        serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() throws Exception {
                ChannelPipeline pipeline = Channels.pipeline();
                //将数据转换为String类型
                pipeline.addLast("decoder",new StringDecoder());
                pipeline.addLast("encoder",new StringEncoder());
                pipeline.addLast("serverHandler",new ServerHandler());
                return pipeline;
            }
        });
        //绑定端口号
        serverBootstrap.bind(new InetSocketAddress(8080));
        System.out.println("Netty服务器端已经启动...");

    }
}

class ServerHandler extends SimpleChannelHandler{
    /**
     * 通道关闭的时候触发
     */
    @Override
    public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("通道关闭的时候触发:channelClosed");
    }
    /**
     * 必须是连接已经建立,关闭通道的时候才会触发
     */
    @Override
    public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("必须是连接已经建立,关闭通道的时候才会触发:channelDisconnected");
    }
    /**
     * 捕获异常
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
        System.out.println("捕获异常:exceptionCaught");
    }
    /**
     * 接受消息
     */
    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
        System.out.println("服务器端接受到客户端的消息:"+e.getMessage());
        //回复内容
        ctx.getChannel().write("您好,主人暂时不在,有事请留言!!!");
    }
}
Netty客户端
public class NettyClient {
    public static void main(String[] args) {
        System.out.println("Netty客户端已经启动...");
        //创建服务类对象
        ClientBootstrap clientBootstrap = new ClientBootstrap();
        //创建两个线程池,分别为监听端口,监听NIO
        ExecutorService boos = Executors.newCachedThreadPool();
        ExecutorService worker = Executors.newCachedThreadPool();
        //设置工程,并把两个线程池加入其中
        clientBootstrap.setFactory(new NioClientSocketChannelFactory(boos,worker));
        //设置管道工程
        clientBootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() throws Exception {
                ChannelPipeline pipeline = Channels.pipeline();
                //将数据转换为String类型
                pipeline.addLast("decoder",new StringDecoder());
                pipeline.addLast("encoder",new StringEncoder());
                pipeline.addLast("clientHandler",new ClientHandler());
                return pipeline;
            }
        });
        //连接服务端
        ChannelFuture connect = clientBootstrap.connect(new InetSocketAddress("127.0.0.1", 8080));
        Channel channel = connect.getChannel();
        System.out.println("Client Start");
        Scanner scanner = new Scanner(System.in);
        while (true){
            System.out.println("请输入内容:");
            String str = scanner.next();
            channel.write(str);
        }

    }
}

class ClientHandler extends SimpleChannelHandler {
    /**
     * 通道关闭的时候触发
     */
    @Override
    public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("通道关闭的时候触发:channelClosed");
    }
    /**
     * 必须是连接已经建立,关闭通道的时候才会触发
     */
    @Override
    public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("必须是连接已经建立,关闭通道的时候才会触发:channelDisconnected");
    }
    /**
     * 捕获异常
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
        System.out.println("捕获异常:exceptionCaught");
    }
    /**
     * 接受消息
     */
    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
        System.out.println("服务器端向客户端回复内容:"+e.getMessage());
        //回复内容
//        ctx.getChannel().write("您好,主人暂时不在,有事请留言!!!");
    }
}
运行结果

服务器端:
这里写图片描述
客户端:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值