第一節說的例子太簡單,實際狀況當中咱們要對消息進行處理。如今咱們來寫一個時間服務器。時間服務器的TimeServer文件和第一節裏面差很少,改幾個類名就能夠了,咱們只要看下時間服務器的handler。在連接創建之後,服務器向客戶端發送系統時間,這個時間是32比特的整數,發送完畢以後就關閉服務器,而不用一直保持讀取狀態,因此在這裏咱們在Handler裏面不可以使用channelRead()方法,而是使用channelActive()方法。java
package com.hengzecn.NettyClient; import java.util.Date; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; public class TimeClientHandler extends ChannelInboundHandlerAdapter { private ByteBuf buf; @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { buf = ctx.alloc().buffer(4); } @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { buf.release(); buf = null; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg){ ByteBuf m = (ByteBuf) msg; buf.writeBytes(m); m.release(); if(buf.readableBytes() >= 4){ long currentTimeMillis = (buf.readUnsignedInt() - 2208988800L) * 1000L; System.out.println(new Date(currentTimeMillis)); ctx.close(); } // 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(); } }
咱們用Netty來寫個客戶端測試下:bootstrap
package com.hengzecn.NettyClient; import io.netty.bootstrap.Bootstrap; 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; import io.netty.channel.socket.nio.NioSocketChannel; public class TimeClient { public static void main(String[] args) throws Exception{ String host = "127.0.0.1"; int port = 8080; EventLoopGroup workerGroup = new NioEventLoopGroup(); try{ Bootstrap b = new Bootstrap(); b.group(workerGroup); b.channel(NioSocketChannel.class); b.option(ChannelOption.SO_KEEPALIVE, true); 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(); f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); } } }
客戶端的Handler使用channelRead來讀取服務器端發來的信息:服務器
package com.hengzecn.NettyClient; import java.util.Date; import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; public class TimeClientHandler extends ChannelInboundHandlerAdapter { private ByteBuf buf; @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { buf = ctx.alloc().buffer(4); } @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { buf.release(); buf = null; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg){ ByteBuf m = (ByteBuf) msg; buf.writeBytes(m); m.release(); if(buf.readableBytes() >= 4){ long currentTimeMillis = (buf.readUnsignedInt() - 2208988800L) * 1000L; System.out.println(new Date(currentTimeMillis)); ctx.close(); } // 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(); } }
運行客戶端,成功收到了服務器發來的時間信息,收到信息後服務就關閉了,以下圖所示:異步