Netty学习笔记四:Echo服务和Netty项目的搭建

Posted java开发架构师

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Netty学习笔记四:Echo服务和Netty项目的搭建相关的知识,希望对你有一定的参考价值。


1. Netty学习笔记四:Echo服务和Netty项目的搭建

1.1. 什么是Echo服务1.2. Echo服务端程序编写1.3. Echo客户端编写1.4. Echo服务中的名词解析

1.1. 什么是Echo服务

  1. Echo服务就是一个应答服务,客户端发送什么数据,服务端就响应对应的数据,是一个非常有的用于调试和检测的服务。

1.2. Echo服务端程序编写

  1. EchoServer服务端

一、绑定端口

二、创建主从线程组

三、启动线程组,指定通道 类型,处理传过来的数据内容。

四、监听端口,关闭端口

五、释放线程。

 1public class EchoServer {
2    private int port;
3    public EchoServer(int port){
4        this.port=port;
5    }
6    public void run() throws InterruptedException {
7        //创建主从线程组。
8        EventLoopGroup bossGroup=new NioEventLoopGroup();
9        EventLoopGroup workGroup=new NioEventLoopGroup();
10        try{
11            //配置线程组启动类,Netty框架已经封装好了。创建一个启动对象
12            ServerBootstrap serverBootstrap=new ServerBootstrap();
13            //将需要启动的线程组包裹进去。//可以通过链式的调用方法,指定Channel类型。
14            serverBootstrap.group(bossGroup,workGroup)
15                .channel(NioserverSocketChannel.class)//每启动一个线程组就要指定一个通道类型。
16                .childHandler(new ChannelInitializer<SocketChannel>() {//当建立通道连接时需要进行处理。
17                    protected void initChannel(SocketChannel ch) throws Exception {
18                        ch.pipeline().addLast(new EchoServerHandler());
19                    }
20                });
21            System.out.println("Echo 服务器启动ing");
22            //绑定端口,需要同步等待。
23            ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
24            //等待服务端,监听端口关闭
25            channelFuture.channel().closeFuture().sync();
26        }finally {
27            //优雅退出,释放线程池。
28            workGroup.shutdownGracefully();
29            bossGroup.shutdownGracefully();
30        }
31    }
32    public static void main(String[] args) throws InterruptedException {
33        int port =7070;
34        if(args.length>0){
35            port=Integer.parseInt(args[0]);
36        }
37        new EchoServer(port).run();
38    }
39}
  1. 处理类

 1public class EchoServerHandler extends ChannelInboundHandlerAdapter {
2    @Override
3    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
4       //ByteBuf是Netty封装的ByteBuffer。
5        ByteBuf data= (ByteBuf)msg;
6        System.out.println("服务端收到数据:"+data.toString(CharsetUtil.UTF_8));
7        //回写过去,并刷新管道。
8        ctx.writeAndFlush(data);
9    }
10    @Override
11    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
12        System.out.println("EchoServerHandle channelReadComplete");
13    }
14    @Override
15    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
16        cause.printStackTrace();
17        ctx.close();
18    }
19}

1.3. Echo客户端编写

  1. EchoClient主类

 1public class EchoClient {
2    private int port;
3    private String host;
4    public EchoClient(String host,int port){
5        this.port=port;
6        this.host=host;
7    }
8    public void start() throws InterruptedException {
9        EventLoopGroup group=new NioEventLoopGroup();
10        try{
11            Bootstrap bootstrap =new Bootstrap();
12            bootstrap.group(group)
13                .channel(NioSocketChannel.class)
14                .remoteAddress(new InetSocketAddress(host,port))
15                .handler(new ChannelInitializer<SocketChannel>() {
16                    protected void initChannel(SocketChannel ch) throws Exception {
17                        ch.pipeline().addLast(new EchoClientHandler());
18                    }
19                });
20            //连接到服务器,connect是异步连接,在调用同步等待sync,等待连接成功。
21            ChannelFuture channelFulture = bootstrap.connect().sync();
22            //阻塞住,直到客户端通道关闭。
23            channelFulture.channel().closeFuture().sync();
24        }finally {
25            //优雅退出释放NIO线程。
26            group.shutdownGracefully();
27        }
28    }
29    public static void main(String[] args) throws InterruptedException {
30        new EchoClient("127.0.0.1",7070).start();
31    }
32}
  1. EchoClientHandler处理类

一、与服务端处理类继承的不一样,但是实质是一样的。

二、打印顺序是,先走Active()方法,先激活,表示和服务端建立了通道。

三、读取服务端的数据,

四、读取完成。进入channelReadComplete()方法。

 1public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf{
2    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {
3        System.out.println("Client received...."+msg.toString(CharsetUtil.UTF_8));
4    }
5    @Override
6    public void channelActive(ChannelHandlerContext ctx) throws Exception {
7        System.out.println("Active");
8        //创建一个缓存。使用Unpooled工具类。
9        ctx.writeAndFlush(Unpooled.copiedBuffer("世界你好,我是zkf",CharsetUtil.UTF_8));
10    }
11    @Override
12    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
13        System.out.println("EchoClient channelReadComplete");
14    }
15
16    @Override
17    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
18        cause.printStackTrace();
19        ctx.close();
20    }
21}

1.4. Echo服务中的名词解析

  1. EventLoop和EventLoopGroup

线程和线程组,前者可以理解为线程,后者可以理解为线程组。

  1. BootStrap

启动引导类,用于配置线程组,启动的时候,同时启动线程组,以及开启通道,初始化通道。和一些处理。

  1. channel

channel是客户端和服务端建立的一个连接,是一个Socket连接,具有生命周期,建立成功,读取数据,读取完成,出现异常等。

  1. channelHandler和channelPipeline

channelhandler是做处理的,对接收的数据进行处理到要直接或间接继承channelHandler。

channelPipeline就好比一个处理工厂,可以添加很多handler处理类,当进入channelHandler后都要经过pipeline添加的handler进行处理。

  1. 个人理解:

就像一个滤水系统,BootStrap是滤水系统的开关,它将滤水系统与水资源连接起来,然后产生一个通道Channel,每个通道里面有一个净水处理系统,即:ChannelHandler,每个净水系统里面有很多处理管道,即:Handler,处理管道是活的,可以添加,卸掉。这些动作都要pipeline这个工具类来实现。

以上是关于Netty学习笔记四:Echo服务和Netty项目的搭建的主要内容,如果未能解决你的问题,请参考以下文章

Netty学习笔记:Netty核心模块组件

Netty 4.x学习笔记——线程模型

Netty 笔记-第一个 Netty 程序

Netty实战之构建Echo服务器和客户端

Netty学习笔记15 Netty Attribute使用

Netty学习笔记15 Netty Attribute使用