关于java:Netty-简易实战傻瓜都能看懂

作者:rickiyang

出处:www.cnblogs.com/rickiyang/p/11074237.html

这一节咱们来解说Netty,应用Netty之前咱们先理解一下Netty能做什么,有为而学,岂不是白费力气!

1.应用Netty可能做什么

  1. 开发异步、非阻塞的TCP网络应用程序;
  2. 开发异步、非阻塞的UDP网络应用程序;
  3. 开发异步文件传输应用程序;
  4. 开发异步HTTP服务端和客户端应用程序;
  5. 提供对多种编解码框架的集成,包含谷歌的Protobuf、Jboss marshalling、Java序列化、压缩编解码、XML解码、字符串编解码等,这些编解码框架能够被用户间接应用;
  6. 提供形式多样的编解码根底类库,能够十分不便的实现公有协定栈编解码框架的二次定制和开发;
  7. 基于职责链模式的Pipeline-Handler机制,用户能够十分不便的对网络事件进行拦挡和定制;
  8. 所有的IO操作都是异步的,用户能够通过Future-Listener机制被动Get后果或者由IO线程操作实现之后被动Notify后果,用户的业务线程不须要同步期待;
  9. IP黑白名单管制;
  10. 打印消息码流;
  11. 流量管制和整形;
  12. 性能统计;
  13. 基于链路闲暇事件检测的心跳检测

2. Netty罕用类解说

在这里咱们就一些咱们罕用到的类做大抵的解说,而后再写入门程序的时候大抵晓得每一行都讲了什么。

EventLoop,EventLoopGroup

EventLoop目标是为Channel解决IO操作,一个EventLoop能够为多个Channel服务,EventLoopGroup会蕴含多个EventLoop。

BootStrap,ServerBootstrap

一个Netty利用通常由一个Bootstrap开始,它次要作用是配置整个Netty程序,串联起各个组件。

ChannelInitializer

当一个链接建设时,咱们须要晓得怎么来接管或者发送数据,当然,咱们有各种各样的Handler实现来解决它,那么ChannelInitializer便是用来配置这些Handler,它会提供一个ChannelPipeline,并把Handler退出到ChannelPipeline。

Handler

为了反对各种协定和解决数据的形式,便诞生了Handler组件。Handler次要用来解决各种事件,这里的事件很宽泛,比方能够是连贯、数据接管、异样、数据转换等。

ChannelInboundHandler

一个最罕用的Handler。这个Handler的作用就是解决接管到数据时的事件,也就是说,咱们的业务逻辑个别就是写在这个Handler外面的,ChannelInboundHandler就是用来解决咱们的外围业务逻辑。

Future

在Netty中所有的IO操作都是异步的,因而,你不能立即得悉音讯是否被正确处理,然而咱们能够过一会等它执行实现或者间接注册一个监听,具体的实现就是通过Future和ChannelFutures,他们能够注册一个监听,当操作执行胜利或失败时监听会主动触发。总之,所有的操作都会返回一个ChannelFuture。

3. 第一个Helloworld

下面咱们曾经对罕用类进行阐明,上面咱们就应用这些类来构建咱们的第一个入门程序,本示例我应用的是maven来构建工程,如果你应用的是一般的我的项目则跳过第一步。

首先引入maven jar包:

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

上面咱们来写客户端:

public class HelloWorldClient {
    private  int port;
    private  String address;

    public HelloWorldClient(int port,String address) {
        this.port = port;
        this.address = address;
    }

    public void start(){
        EventLoopGroup group = new NioEventLoopGroup();

        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group)
                .channel(NioSocketChannel.class)
                .handler(new ClientChannelInitializer());

        try {
            Channel channel = bootstrap.connect(address,port).sync().channel();
            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
            for(;;){
                String msg = reader.readLine();
                if(msg == null){
                    continue;
                }             
                channel.writeAndFlush(msg + "\r\n");
            }         
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            group.shutdownGracefully();
        }

    }

    public static void main(String[] args) {
        HelloWorldClient client = new HelloWorldClient(7788,"127.0.0.1");
        client.start();
    }
}

ChannelInitializer用来配置解决数据的handler:

public class ClientChannelInitializer extends  ChannelInitializer<SocketChannel> {

    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();

        /*
         * 这个中央的 必须和服务端对应上。否则无奈失常解码和编码
         *
         * 解码和编码 我将会在下一节为大家具体的解说。临时不做具体的形容
         *
         * /        
        pipeline.addLast("decoder", new StringDecoder());
        pipeline.addLast("encoder", new StringEncoder());

        // 咱们本人的handler
        pipeline.addLast("handler", new HelloWorldClientHandler());
    }
}

写一个咱们本人的handler,用本人的形式来解决数据:

public class HelloWorldClientHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("server say : "+msg.toString());
    }

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

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

客户端咱们写完了,上面开始写服务器端:

public class HelloWordServer {
    private int port;

    public HelloWordServer(int port) {
        this.port = port;
    }

    public void start(){
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workGroup = new NioEventLoopGroup();

        ServerBootstrap server = new ServerBootstrap().group(bossGroup,workGroup)
                                    .channel(NioServerSocketChannel.class)
                                    .childHandler(new ServerChannelInitializer());

        try {
            ChannelFuture future = server.bind(port).sync();
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            bossGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        HelloWordServer server = new HelloWordServer(7788);
        server.start();
    }
}

服务端的ChannelInitializer:

public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        ChannelPipeline pipeline = socketChannel.pipeline();      

        // 字符串解码 和 编码
        pipeline.addLast("decoder", new StringDecoder());
        pipeline.addLast("encoder", new StringEncoder());

        // 本人的逻辑Handler
        pipeline.addLast("handler", new HelloWordServerHandler());
    }
}

服务器端的handler:

public class HelloWordServerHandler extends ChannelInboundHandlerAdapter {

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println(ctx.channel().remoteAddress()+"===>server: "+msg.toString());
        ctx.write("received your msg");
        ctx.flush();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
        ctx.close();
    }
}

下面服务器端和客户端的代码都曾经写完,上面咱们先启动服务端,而后启动客户端,程序中我是在客户端让手动输出,输出完结之后回车,服务器端即可承受数据。

客户端:

服务端:

近期热文举荐:

1.1,000+ 道 Java面试题及答案整顿(2021最新版)

2.终于靠开源我的项目弄到 IntelliJ IDEA 激活码了,真香!

3.阿里 Mock 工具正式开源,干掉市面上所有 Mock 工具!

4.Spring Cloud 2020.0.0 正式公布,全新颠覆性版本!

5.《Java开发手册(嵩山版)》最新公布,速速下载!

感觉不错,别忘了顺手点赞+转发哦!

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理