Netty5入门(2)

四、Time协议

继续测试《netty5用户指南》中的Time协议。

1、一个封装时间的特殊的POJO类

首先实现UnixTime类:

package com.ydtf;

 

import java.util.Date;

 

public class UnixTime {

 

    private final int value;

 

    public UnixTime() {

       this((int) (System.currentTimeMillis() / 1000L+ 2208988800L));

    }

 

    public UnixTime(int value) {

       this.value = value;

    }

 

    public int value() {

       return value;

    }

 

    @Override

    public String toString() {

       return new Date((value() - 2208988800L) *1000L).toString();

    }

}

2、将ByteBuf转换为POJO

然后是TimeDecoder类:

package com.ydtf;

 

import java.util.List;

 

import io.netty.buffer.ByteBuf;

import io.netty.channel.ChannelHandlerContext;

import io.netty.handler.codec.ByteToMessageDecoder;

 

 

public class TimeDecoder extends ByteToMessageDecoder { // (1)

 

   @Override

   protected void decode(ChannelHandlerContext ctx, ByteBuf in,

         List<Object>out) throws Exception {

      if (in.readableBytes()< 4) {

           return;

       }

 

       out.add(new UnixTime(in.readInt()));

   }

}

3、将POJO转换为ByteBuf

TimeEncoder,用于进行UnixTime –>ByteBuf的转换。

package com.ydtf;

 

import io.netty.buffer.ByteBuf;

import io.netty.channel.ChannelHandlerContext;

import io.netty.handler.codec.MessageToByteEncoder;

 

public class TimeEncoder extends MessageToByteEncoder<UnixTime> {

 

   @Override

   protected void encode(ChannelHandlerContext ctx, UnixTime msg, ByteBuf out)

         throws Exception {

      out.writeInt(msg.value());

   }

}

4、服务端的处理

然后是服务端的handler:

package com.ydtf;

 

import io.netty.buffer.ByteBuf;

import io.netty.channel.ChannelFuture;

import io.netty.channel.ChannelFutureListener;

import io.netty.channel.ChannelHandlerAdapter;

import io.netty.channel.ChannelHandlerContext;

 

public classTimeServerHandler extendsChannelHandlerAdapter {

 

    @Override

    public voidchannelActive(ChannelHandlerContext ctx) {

       ChannelFuture f = ctx.writeAndFlush(new UnixTime());

       f.addListener(ChannelFutureListener.CLOSE);

    }

 

    @Override

    public voidexceptionCaught(ChannelHandlerContext ctx, Throwable cause) {

       cause.printStackTrace();

       ctx.close();

    }

}

5、客户端的处理

客户端的handler:

package com.ydtf;

 

import io.netty.channel.ChannelHandlerAdapter;

import io.netty.channel.ChannelHandlerContext;

 

public classTimeClientHandler extendsChannelHandlerAdapter {

   @Override

   public voidchannelRead(ChannelHandlerContext ctx, Object msg) {

       UnixTime m = (UnixTime) msg;

       System.out.println(m);

       ctx.close();

   }

    @Override

    public voidexceptionCaught(ChannelHandlerContext ctx, Throwable cause) {

       cause.printStackTrace();

       ctx.close();

    }

}

6、服务端主类

package com.ydtf;

 

import io.netty.bootstrap.ServerBootstrap;

import io.netty.channel.ChannelFuture;

import io.netty.channel.ChannelInitializer;

import io.netty.channel.ChannelOption;

import io.netty.channel.EventLoopGroup;

import io.netty.channel.nio.NioEventLoopGroup;

import io.netty.channel.socket.SocketChannel;

importio.netty.channel.socket.nio.NioServerSocketChannel;

 

public class TimeServer {

   private int port;

 

    public TimeServer(int port) {

       this.port = port;

    }

 

    public void run() throws Exception {

       EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)

       EventLoopGroup workerGroup = new NioEventLoopGroup();

       try {

           ServerBootstrap b = new ServerBootstrap(); // (2)

           b.group(bossGroup, workerGroup)

            .channel(NioServerSocketChannel.class) // (3)

            .childHandler(newChannelInitializer<SocketChannel>() { // (4)

                 @Override

                 public voidinitChannel(SocketChannel ch) throws Exception {

                     ch.pipeline().addLast(new TimeEncoder(), new TimeServerHandler());

                 }

            })

            .option(ChannelOption.SO_BACKLOG, 128)          // (5)

            .childOption(ChannelOption.SO_KEEPALIVE, true); // (6)

 

           ChannelFuture f = b.bind(port).sync(); // (7)

           f.channel().closeFuture().sync();

       } finally {

           workerGroup.shutdownGracefully();

           bossGroup.shutdownGracefully();

       }

    }

 

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

       int port;

       if (args.length > 0) {

           port = Integer.parseInt(args[0]);

       } else {

           port = 8080;

       }

       new TimeServer(port).run();

    }

}

7、客户端主类

packagecom.ydtf;

 

importio.netty.bootstrap.Bootstrap;

importio.netty.channel.ChannelFuture;

importio.netty.channel.ChannelInitializer;

import io.netty.channel.ChannelOption;

importio.netty.channel.EventLoopGroup;

importio.netty.channel.nio.NioEventLoopGroup;

importio.netty.channel.socket.SocketChannel;

importio.netty.channel.socket.nio.NioSocketChannel;

 

publicclass TimeClient {

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

        String host = args[0];

        int port = Integer.parseInt(args[1]);

        EventLoopGroup workerGroup = newNioEventLoopGroup();

 

        try {

            Bootstrap b = new Bootstrap(); //(1)

           b.group(workerGroup); // (2)

            b.channel(NioSocketChannel.class);// (3)

           b.option(ChannelOption.SO_KEEPALIVE, true); // (4)

            b.handler(newChannelInitializer<SocketChannel>() {

                @Override

                public voidinitChannel(SocketChannel ch) throws Exception {

                    ch.pipeline().addLast(newTimeDecoder(), new TimeClientHandler());

                }

            });

 

            // Start the client.

            ChannelFuture f = b.connect(host,port).sync(); // (5)

 

            // Wait until the connection isclosed.

            f.channel().closeFuture().sync();

        } finally {

            workerGroup.shutdownGracefully();

        }

    }

}

8、运行

在TimeServer.java上右键,Run as >> Java Application,启动服务端。

然后在TimeClient.java上右键,Run as >> Run Configurations…,在弹出的窗口中设置Name和Main Class:

技术分享

Name设置一个和现有配置不重复的就可以了,比如TimeClient1、TimeClien(2)等。点击Mainclass右边的Search…按钮,选择TimeClient类。

然后点Arguments,添加两个运行参数localhost和8080:

技术分享

然后点击窗口右下角的Run按钮。这是你将在客户端的Console窗口中看见一个日期输出。

如果想分别查看服务端和客户端的Console输出,请点击Display Selected Console按钮:

技术分享


郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。