Netty(7)-传对象
改造timer,即客户端与服务端建立连接后,服务端主动向客户端发送当前时间。
server:
ch.pipeline().addLast(new TimeEncoder()); ch.pipeline().addLast(new TimeServerHandler());
TimeServerHandler
public class TimeServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelActive(ChannelHandlerContext ctx) throws Exception {//(1) ChannelFuture f = ctx.writeAndFlush(new UnixTime()); f.addListener(ChannelFutureListener.CLOSE);//因为是write,传递给的不是ByteToMessageDecoder } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }
TimeEncoder
public class TimeEncoder extends ChannelOutboundHandlerAdapter { @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { UnixTime m = (UnixTime)msg; ByteBuf encoded = ctx.alloc().buffer(4); encoded.writeInt((int)m.value()); ctx.write(encoded,promise);//(1) } }
注意:
1、在TimeServerHandler中,ctx.writeAndFlush(new UnixTime()),已经writeAndFlush了,所以执行过程:TimeServerHandler(write) ---->TimeEncoder(write)--->ChannelOutboundHandlerAdapter(flush)。
如果在TimeServerHandler中只写write不写flush,那么不会自动执行ChannelOutboundHandlerAdapter中的flush方法,从而无法发送到网络。
如果在TimeServerHandler中只写write不写flush,但是在TimeEncoder中执行flush方法,不执行ChannelOutboundHandlerAdapter中的flush方法,但能发送到网络。
总结:在ChannelPipeline中传输的handler,只要在任意一个handler钟写flush,都会发送到网络。
2、TimeEncoder也可以写成:
public class TimeEncoder extends MessageToByteEncoder<UnixTime> { @Override protected void encode(ChannelHandlerContext ctx, UnixTime msg, ByteBuf out) throws Exception { out.writeInt((int)msg.value()); } }
TimeClient
ch.pipeline().addLast(new TimeDecoder()); ch.pipeline().addLast(new TimeClientHandler());
TimeDecoder
public class TimeDecoder extends ByteToMessageDecoder { @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { if (in.readableBytes() < 4) { return ; } out.add(new UnixTime(in.readUnsignedInt())); } }
TimeClientHandler
public class TimeClientHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { UnixTime m = (UnixTime) msg; log.info("{}", m); ctx.close(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } }