Netty 4.x 寫(xiě)個(gè)時(shí)間客戶端

2018-10-26 09:51 更新

寫(xiě)個(gè)時(shí)間客戶端

不像 DISCARD 和 ECHO 的服務(wù)端,對(duì)于 TIME 協(xié)議我們需要一個(gè)客戶端,因?yàn)槿藗儾荒馨岩粋€(gè)32位的二進(jìn)制數(shù)據(jù)翻譯成一個(gè)日期或者日歷。在這一部分,我們將會(huì)討論如何確保服務(wù)端是正常工作的,并且學(xué)習(xí)怎樣用Netty 編寫(xiě)一個(gè)客戶端。

在 Netty 中,編寫(xiě)服務(wù)端和客戶端最大的并且唯一不同的使用了不同的BootStrapChannel的實(shí)現(xiàn)。請(qǐng)看一下下面的代碼:

    public class TimeClient {

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

            String host = args[0];
            int port = Integer.parseInt(args[1]);
            EventLoopGroup workerGroup = new NioEventLoopGroup();

            try {
                Bootstrap b = new Bootstrap(); // (1)
                b.group(workerGroup); // (2)
                b.channel(NioSocketChannel.class); // (3)
                b.option(ChannelOption.SO_KEEPALIVE, true); // (4)
                b.handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new TimeClientHandler());
                    }
                });

                // 啟動(dòng)客戶端
                ChannelFuture f = b.connect(host, port).sync(); // (5)

                // 等待連接關(guān)閉
                f.channel().closeFuture().sync();
            } finally {
                workerGroup.shutdownGracefully();
            }
        }
    }

1.BootStrap 和 ServerBootstrap 類(lèi)似,不過(guò)他是對(duì)非服務(wù)端的 channel 而言,比如客戶端或者無(wú)連接傳輸模式的 channel。

2.如果你只指定了一個(gè) EventLoopGroup,那他就會(huì)即作為一個(gè) boss group ,也會(huì)作為一個(gè) workder group,盡管客戶端不需要使用到 boss worker 。

3.代替NioServerSocketChannel的是NioSocketChannel,這個(gè)類(lèi)在客戶端channel 被創(chuàng)建時(shí)使用。

4.不像在使用 ServerBootstrap 時(shí)需要用 childOption() 方法,因?yàn)榭蛻舳说?SocketChannel 沒(méi)有父親。

5.我們用 connect() 方法代替了 bind() 方法。

正如你看到的,他和服務(wù)端的代碼是不一樣的。ChannelHandler 是如何實(shí)現(xiàn)的?他應(yīng)該從服務(wù)端接受一個(gè)32位的整數(shù)消息,把他翻譯成人們能讀懂的格式,并打印翻譯好的時(shí)間,最后關(guān)閉連接:

    import java.util.Date;

    public class TimeClientHandler extends ChannelInboundHandlerAdapter {
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) {
            ByteBuf m = (ByteBuf) msg; // (1)
            try {
                long currentTimeMillis = (m.readUnsignedInt() - 2208988800L) * 1000L;
                System.out.println(new Date(currentTimeMillis));
                ctx.close();
            } finally {
                m.release();
            }
        }

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

1.在TCP/IP中,Netty 會(huì)把讀到的數(shù)據(jù)放到 ByteBuf 的數(shù)據(jù)結(jié)構(gòu)中。

這樣看起來(lái)非常簡(jiǎn)單,并且和服務(wù)端的那個(gè)例子的代碼也相差不多。然而,處理器有時(shí)候會(huì)因?yàn)閽伋?IndexOutOfBoundsException 而拒絕工作。在下個(gè)部分我們會(huì)討論為什么會(huì)發(fā)生這種情況。

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)