Netty学习(二)-Helloworld Netty

原创 2017年03月25日 10:15:17

这一节我们来讲解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();
    }
}

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

客户端:

服务端:

版权声明:本文为博主原创文章,未经博主允许不得转载。

Netty学习(二)-Helloworld Netty

这一节我们来讲解Netty,使用Netty之前我们先了解一下Netty能做什么,无为而学,岂不是白费力气!1.使用Netty能够做什么 开发异步、非阻塞的TCP网络应用程序; 开发异步、非阻塞的UDP...
  • a953713428
  • a953713428
  • 2017年03月25日 10:15
  • 671

Netty学习(四)-TCP粘包和拆包

我们都知道TCP是基于字节流的传输协议。那么数据在通信层传播其实就像河水一样并没有明显的分界线,而数据具体表示什么意思什么地方有句号什么地方有分号这个对于TCP底层来说并不清楚。应用层向TCP层发送用...
  • a953713428
  • a953713428
  • 2017年03月28日 09:17
  • 672

一起学Netty(一)之 Hello Netty

四月份花了大概一个月的时间翻译了2015年12月出版的《Netty in Action》 说实话,翻译完了,感觉只是对Netty有了一些初步的了解,对Netty的模型在脑海中也是有了初步的雏形,好记性...
  • linuu
  • linuu
  • 2016年05月07日 17:13
  • 9029

Netty框架的学习经历初级篇---helloworld

每一个程序猿都对helloworld有一段特殊的感情! 我的学习也是从一段helloworld代码开始的。一开始下载了一个pdf版的netty权威指南,该书是以netty5.0版本讲述的,到nett...
  • chuanren1991
  • chuanren1991
  • 2016年10月26日 11:51
  • 1982

Netty使用实例

贴上两个自己写好的例子,以便备注,以下两个例子基于netty-3.5.7.Final.jar用Junit进行测试   第一个例子:简单的发送字符串,接收字符串“Hello, World” ...
  • qq_26562641
  • qq_26562641
  • 2015年12月11日 15:38
  • 586

一起学Netty(一)之 Hello Netty

案例说明:客户端发送一个信息到服务器端,服务器端将信息原样返回 maven的依赖,我们如下: [html] view plain copy ...
  • z69183787
  • z69183787
  • 2016年10月31日 10:21
  • 1025

netty——helloworld

首先要引入netty的包,可以在http://netty.io/downloads.html 选择自己需要的版本下载,然后引入它里面的all的jar包。 如果你的项目使用了maven,则可以直接用下...
  • wang_keng
  • wang_keng
  • 2017年05月23日 16:45
  • 199

Netty初步之Hello World

Java的学习是从Hello word开始的,Netty也从这里开始吧。这里的例子比较简单,后面会慢慢的对Netty的一些复杂应用、Netty的原理进行一些解析。本文主要是列举Netty初步使用的一个...
  • kobejayandy
  • kobejayandy
  • 2014年02月18日 23:43
  • 3723

一起学Netty(十五)之 AttributeMap属性

本来没打算研究这个东西的,一开始觉得没啥用,甚至觉得这个东西有点鸡肋,不过慢慢接触之后,发现了这个AttributeMap的重要性 初学这个东西,我们还是先理解AttributeMap的用法吧 ...
  • u010154380
  • u010154380
  • 2017年10月05日 11:30
  • 95

Java NIO框架--Netty4的简单示例

摘要: Java NIO框架--Netty4的简单示例 简介          相比Netty3, Netty4有很多显著的变化:         NioEventLoopGroup 是一个处理I...
  • beagreatprogrammer
  • beagreatprogrammer
  • 2016年11月25日 19:27
  • 563
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Netty学习(二)-Helloworld Netty
举报原因:
原因补充:

(最多只允许输入30个字)