鍍金池/ 教程/ Java/ 寫個時間客戶端
Netty 實(shí)現(xiàn) WebSocket 聊天功能
總結(jié)
寫個時間客戶端
寫個丟棄服務(wù)器
問題
開始之前
關(guān)閉你的應(yīng)用
開始
用POJO代替ByteBuf
總結(jié)
架構(gòu)總覽
豐富的緩沖實(shí)現(xiàn)
解決
寫個應(yīng)答服務(wù)器
I/O API 統(tǒng)一的異步 I/O API
適用快速開發(fā)的高級組件
處理一個基于流的傳輸
Netty 實(shí)現(xiàn)聊天功能
基于攔截鏈模式的事件模型
寫個時間服務(wù)器
查看收到的數(shù)據(jù)

寫個時間客戶端

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

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

    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());
                    }
                });

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

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

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

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

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

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

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

正如你看到的,他和服務(wù)端的代碼是不一樣的。ChannelHandler 是如何實(shí)現(xiàn)的?他應(yīng)該從服務(wù)端接受一個32位的整數(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 會把讀到的數(shù)據(jù)放到 ByteBuf 的數(shù)據(jù)結(jié)構(gòu)中。

http://wiki.jikexueyuan.com/project/netty-4-user-guide/images/2.1.jpg" alt="" />

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

上一篇:開始之前下一篇:架構(gòu)總覽