当前位置: 首页 > news >正文

关于Netty的一点初步认识

关于Netty的一点初步认识

最初接触

刚开始接触Netty时,搜索相关资料及教程,就看到了关于 Netty5 的一些教程;
打开Netty官网,却没有找到关于Netty5的影子,只感觉了有点奇怪。

Netty官方对应Github的releases上,最新的更新也只是关于4.x的版本;
后来在mvnrepository上看到了关于netty5的影子,更新时间为2015年3月,后来在github releases中找到了netty5的版本,不过只更新到netty-5.0.0.Alpha2版本就再也没有更新过;

Netty3 与 Netty4

后来进行了一些简单的对比,总结了一些简单的区别:

  • 3.0.0.CR1 ~ 3.2.10.Final

maven依赖

<!-- https://mvnrepository.com/artifact/org.jboss.netty/netty -->
<!-- 3.0.0.CR1 ~ 3.2.10.Final -->
<dependency>
    <groupId>org.jboss.netty</groupId>
    <artifactId>netty</artifactId>
    <version>3.2.10.Final</version>
</dependency>

包名以org.jboss.netty开头;

  • 3.3.0.Final ~ 3.10.6.Final

maven依赖

<!-- https://mvnrepository.com/artifact/io.netty/netty -->
<!-- 3.3.0.Final ~ 3.10.6.Final -->
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty</artifactId>
    <version>3.10.6.Final</version>
    <!--<version>3.3.0.Final</version>-->
</dependency>

包名也是以org.jboss.netty开头,只是maven依赖的groupId名发生一些改变;

  • 4.0.0.Final ~ 4.1.35.Final

maven依赖

<!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
<!-- 4.0.0.Final ~ 4.1.35.Final ~ 5.0.0.Alpha2 -->
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.35.Final</version>
    <!--<version>5.0.0.Alpha2</version>-->
</dependency>

包名改变为以io.netty开头,maven依赖的artifactId名发生一点改变;

Netty3 的一些简单实践

服务端

NettyServer.java

package morning.cat.netty3.x;

import morning.cat.netty3.x.handle.HelloHandle;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;

import java.net.InetSocketAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @describe: Netty3.x Server
 * @author: morningcat.zhang
 * @date: 2019/4/22 10:37 PM
 */
public class NettyServer {

    public static void main(String[] args) {

        // 服务端
        ServerBootstrap bootstrap = new ServerBootstrap();

        ExecutorService boss = Executors.newCachedThreadPool();
        ExecutorService work = Executors.newCachedThreadPool();

        // 设置 ChannelFactory 工厂
        bootstrap.setFactory(new NioServerSocketChannelFactory(boss, work));

        // 设置 ChannelPipelineFactory 工厂
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() throws Exception {

                // 生成管道
                ChannelPipeline channelPipeline = Channels.pipeline();

                // 接收信息转换成字符串(上行)
                // channelPipeline.addLast("StringDecoder",new StringDecoder());
                // 回写直接写入字符串
                // channelPipeline.addLast("StringEncoder",new StringEncoder());
                channelPipeline.addLast("HelloHandle", new HelloHandle());
                return channelPipeline;
            }
        });

        // 绑定端口
        bootstrap.bind(new InetSocketAddress(59999));
        // telnet 127.0.0.1 59999

        System.out.println("Netty Server start...");

    }
}

HelloHandle.java

package morning.cat.netty3.x.handle;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.*;

/**
 * @describe: Netty3.x Server Handle
 * @author: morningcat.zhang
 * @date: 2019/4/22 10:37 PM
 */
public class HelloHandle extends SimpleChannelHandler {
    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
        ChannelBuffer channelBuffer = (ChannelBuffer) e.getMessage();
        String message = new String(channelBuffer.array());
        System.out.println("接收消息:" + message);

        ChannelBuffer writeMsg = ChannelBuffers.copiedBuffer((" 已接收消息" + message).getBytes());
        ctx.getChannel().write(writeMsg);

        super.messageReceived(ctx, e);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
        System.out.println("发生异常");
        //super.exceptionCaught(ctx, e);
    }

    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("新客户端打开连接" + ctx.getName());
        super.channelConnected(ctx, e);
    }

    @Override
    public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("关闭连接");
        super.channelDisconnected(ctx, e);
    }

    @Override
    public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("关闭通道");
        super.channelClosed(ctx, e);
    }
}

客户端

package morning.cat.netty3.x.client;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.*;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;

import java.net.InetSocketAddress;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @describe: Netty3.x Client
 * @author: morningcat.zhang
 * @date: 2019/4/22 10:37 PM
 */
public class NettyClient {

    public static void main(String[] args) {

        // 客户端
        ClientBootstrap bootstrap = new ClientBootstrap();

        ExecutorService boss = Executors.newCachedThreadPool();
        ExecutorService work = Executors.newCachedThreadPool();

        // 设置 ChannelFactory 工厂
        bootstrap.setFactory(new NioClientSocketChannelFactory(boss, work));

        // 设置管道工厂
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() throws Exception {

                // 获取管道
                ChannelPipeline channelPipeline = Channels.pipeline();

                // Channel Pipeline

                // 接收信息转换成string(上行)
                channelPipeline.addLast("StringDecoder", new StringDecoder());
                // 回写直接写入字符串
                channelPipeline.addLast("StringEncoder", new StringEncoder());

                channelPipeline.addLast("ClientHandle", new ClientHandle());
                return channelPipeline;
            }
        });

        // 绑定端口
        ChannelFuture channelFuture = bootstrap.connect(new InetSocketAddress("127.0.0.1", 59999));
        System.out.println("Netty Client start...");

        Channel channel = channelFuture.getChannel();
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("请输入:");
            channel.write(scanner.next());
        }

    }
}

ClientHandle.java

package morning.cat.netty3.x.client;

import org.jboss.netty.channel.*;

/**
 * @describe: 类描述信息
 * @author: morningcat.zhang
 * @date: 2019/4/22 10:37 PM
 */
public class ClientHandle extends SimpleChannelHandler {
    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
        System.out.println("接收消息:" + e.getMessage());

        super.messageReceived(ctx, e);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
        System.out.println("发生异常");
        super.exceptionCaught(ctx, e);
    }

    @Override
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("打开连接");
        super.channelConnected(ctx, e);
    }

    @Override
    public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("关闭连接");
        super.channelDisconnected(ctx, e);
    }

    @Override
    public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        System.out.println("关闭通道");
        super.channelClosed(ctx, e);
    }
}

Netty4 的一些简单实践

服务端

NettyServer.java

package morning.cat.netty4.x;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

/**
 * @describe: Netty4.x Server
 * @author: morningcat.zhang
 * @date: 2019/4/23 12:13 AM
 */
public class NettyServer {

    public static void main(String[] args) throws InterruptedException {

        // 用来处理I/O操作的多线程事件循环器
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {

            // 服务端
            ServerBootstrap serverBootstrap = new ServerBootstrap();

            // 设置 NioSocket 工厂
            serverBootstrap.group(bossGroup, workerGroup);
            serverBootstrap.channel(NioServerSocketChannel.class);

            // 设置管道工厂 ChannelHandler
            serverBootstrap.childHandler(new ChannelInitializer<Channel>() {
                @Override
                protected void initChannel(Channel channel) throws Exception {

                    ChannelPipeline channelPipeline = channel.pipeline();
                    // 接收信息转换成string(上行)
                    // channelPipeline.addLast("StringDecoder", new StringDecoder());
                    // 回写直接写入字符串
                    // channelPipeline.addLast("StringEncoder", new StringEncoder());

                    //
                    //channelPipeline.addLast("EchoServerHandle", new EchoServerHandle());
                    //
                    // channelPipeline.addLast("HelloHandle", new HelloHandle());

                    //
                    channelPipeline.addLast("HelloHandle", new EchoServerHandle());

                    // channelPipeline.addLast("TimeServerHandler", new TimeServerHandler());
                }
            });

            // 设置参数
            serverBootstrap.option(ChannelOption.SO_BACKLOG, 128);
            serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);

            // 绑定端口
            // telnet 127.0.0.1 51001
            // Bind and start to accept incoming connections.
            ChannelFuture channelFuture = serverBootstrap.bind(51001).sync();
            System.out.println("Netty4 Server start...");


            // Wait until the server socket is closed.
            // In this example, this does not happen, but you can do that to gracefully
            // shut down your server.
            channelFuture.channel().closeFuture().sync();
            System.out.println("closeFuture");
        } finally {
            // 关闭资源
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }

    }
}

EchoServerHandle.java

package morning.cat.netty4.x.server.handle;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelOutboundHandlerAdapter;

import java.nio.charset.Charset;

/**
 * @describe: 类描述信息
 * @author: morningcat.zhang
 * @date: 2019/4/23 3:41 PM
 * @see ChannelOutboundHandlerAdapter,ChannelInboundHandlerAdapter
 */
public class EchoServerHandle extends ChannelInboundHandlerAdapter {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelActive");
        super.channelActive(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelInactive");
        super.channelInactive(ctx);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("channelRead ----->");
        if (msg instanceof ByteBuf) {
            ByteBuf byteBuf = (ByteBuf) msg;
            System.out.println(byteBuf.toString(Charset.defaultCharset()));

        }


        //ByteBuf byteBuf = ByteBufUtil.writeUtf8(ByteBufAllocator.DEFAULT, "server已收到此消息\n");
        //ctx.write(byteBuf);
        //super.channelRead(ctx, msg);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelReadComplete");

//        Channel channel = ctx.channel();
//        channel.writeAndFlush();

        ctx.flush();
        //super.channelReadComplete(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("exceptionCaught");
        super.exceptionCaught(ctx, cause);
    }

}

客户端

package morning.cat.netty4.x.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import morning.cat.netty4.x.client.handle.ClientHandle;
import morning.cat.netty4.x.client.handle.EchoClientHandler;

import java.util.Scanner;

/**
 * @describe: 类描述信息
 * @author: morningcat.zhang
 * @date: 2019/4/23 3:23 PM
 */
public class NettyClient {

    public static void main(String[] args) throws InterruptedException {
        // 用来处理I/O操作的多线程事件循环器
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {

            // 客户端
            Bootstrap clientBootstrap = new Bootstrap();

            // 设置 NioSocket 工厂
            clientBootstrap.group(workerGroup);
            clientBootstrap.channel(NioSocketChannel.class);


            // 设置管道工厂
            clientBootstrap.handler(new ChannelInitializer<Channel>() {
                @Override
                protected void initChannel(Channel channel) throws Exception {

                    ChannelPipeline channelPipeline = channel.pipeline();
                    channelPipeline.addLast("ClientHandle", new EchoClientHandler());
                }
            });

            // 设置参数
            clientBootstrap.option(ChannelOption.SO_BACKLOG, 128);

            // 连接服务端
            ChannelFuture channelFuture = clientBootstrap.connect("127.0.0.1", 51001).sync();
            System.out.println("Netty4 Client start...");


            //channelFuture.channel().closeFuture().sync();

//            Channel channel = channelFuture.channel();
//            Scanner scanner = new Scanner(System.in);
//            while (true) {
//                System.out.print("请输入:");
//                String ss = scanner.next();
//                if (ss.equals("exit")) {
//                    break;
//                }
//                channel.writeAndFlush(ss);
//            }


        } finally {
            // 关闭资源
            workerGroup.shutdownGracefully();
        }
    }
}

package morning.cat.netty4.x.client.handle;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

/**
 * @describe: 类描述信息
 * @author: morningcat.zhang
 * @date: 2019/9/24 2:34 PM
 */
public class EchoClientHandler extends ChannelInboundHandlerAdapter {

    private final ByteBuf firstMessage;

    /**
     * Creates a client-side handler.
     */
    public EchoClientHandler() {
        firstMessage = Unpooled.buffer(128);
//        for (int i = 0; i < firstMessage.capacity(); i++) {
//            firstMessage.writeByte((byte) i);
//        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        firstMessage.writeBytes("HelloNetty".getBytes());
        ctx.writeAndFlush(firstMessage);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ctx.write(msg);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) {
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        // Close the connection when an exception is raised.
        cause.printStackTrace();
        ctx.close();
    }
}

附录

  • 官网

  • github

  • 官网netty4指南

  • 本文工程


对于并发编程网netty5指南,最好结合Netty提供的example工程对比着进行学习及实践。

对于并发编程网上的关于Netty的文章,有些还是值得慢慢学习的。

相关文章:

  • 骨干跳槽让系统成鸡肋 IT主管如何是好
  • 关于 Unsafe 的一点认识与总结
  • Apache服务器虚拟主机设置技术深入解析
  • 转载文章:在Spring Boot中使用条件化的Bean
  • 《赢在用户》8月19日北京书友会报道!
  • kryo浅析
  • 六招彻底防范ARP病毒反复发作
  • 转载:面试前必须要知道的Redis面试题
  • 如何检测网内IP地址是否被占用
  • 转载:Java并发编程-原子类实现
  • Java 中的四种引用类型
  • 美国国家安全局在监视全球网民?
  • 评论:微软的SOA战略
  • SpringBoot 以字符串格式传入时间
  • 基于JAVA的开源工作流引擎(Open Source Workflow Engines Written in Java)
  • hexo+github搭建个人博客
  • SegmentFault for Android 3.0 发布
  • ABAP的include关键字,Java的import, C的include和C4C ABSL 的import比较
  • Android Volley源码解析
  • angular2 简述
  • Angular4 模板式表单用法以及验证
  • EventListener原理
  • FastReport在线报表设计器工作原理
  • IP路由与转发
  • k个最大的数及变种小结
  • PAT A1050
  • React系列之 Redux 架构模式
  • Redash本地开发环境搭建
  • 从@property说起(二)当我们写下@property (nonatomic, weak) id obj时,我们究竟写了什么...
  • 将回调地狱按在地上摩擦的Promise
  • 利用jquery编写加法运算验证码
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 悄悄地说一个bug
  • 使用parted解决大于2T的磁盘分区
  • 数组的操作
  • 双管齐下,VMware的容器新战略
  • 微服务入门【系列视频课程】
  • 微信支付JSAPI,实测!终极方案
  • 责任链模式的两种实现
  • 如何用纯 CSS 创作一个菱形 loader 动画
  • ###项目技术发展史
  • #pragma once
  • ${ }的特别功能
  • (android 地图实战开发)3 在地图上显示当前位置和自定义银行位置
  • (C语言)逆序输出字符串
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (附源码)SSM环卫人员管理平台 计算机毕设36412
  • (过滤器)Filter和(监听器)listener
  • (切换多语言)vantUI+vue-i18n进行国际化配置及新增没有的语言包
  • (转)项目管理杂谈-我所期望的新人
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • .NET Core 通过 Ef Core 操作 Mysql
  • .NET Windows:删除文件夹后立即判断,有可能依然存在
  • .NetCore项目nginx发布
  • .net遍历html中全部的中文,ASP.NET中遍历页面的所有button控件