本文主要是介绍netty-time-Second Solution,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
TimeServer、TimeServerHandler同上篇文章。
package org.q.netty.time2;import java.net.InetSocketAddress;
import java.util.concurrent.Executors;import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;public class TimeClient {private static final String host = "127.0.0.1";private static final int port = 9999;public static void main(String[] args) {ChannelFactory factory = new NioClientSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool());ClientBootstrap bootstrap = new ClientBootstrap(factory);bootstrap.setPipelineFactory(new ChannelPipelineFactory() {public ChannelPipeline getPipeline() throws Exception {return Channels.pipeline(new TimeDecoder(), new TimeClientHandler());}});bootstrap.setOption("tcpNoDelay", true);bootstrap.setOption("keepAlive", true);bootstrap.connect(new InetSocketAddress(host, port));}}
package org.q.netty.time2;import java.text.SimpleDateFormat;
import java.util.Date;import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;public class TimeClientHandler extends SimpleChannelHandler {ChannelBuffer buf = ChannelBuffers.dynamicBuffer(4);@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)throws Exception {e.getCause().printStackTrace();e.getChannel().close();}@Overridepublic void messageReceived(ChannelHandlerContext ctx, MessageEvent e)throws Exception {ChannelBuffer buf = (ChannelBuffer) e.getMessage();long currentTimeMillis = buf.readInt() * 1000L;SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss:SSS");Date date = new Date(currentTimeMillis);System.out.println(date);System.out.println(format.format(date));e.getChannel().close();}}
package org.q.netty.time2;import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.replay.ReplayingDecoder;
import org.jboss.netty.handler.codec.replay.VoidEnum;public class TimeDecoder extends ReplayingDecoder<VoidEnum> {@Overrideprotected Object decode(ChannelHandlerContext ctx, Channel channel,ChannelBuffer buffer, VoidEnum state) throws Exception {return buffer.readBytes(4);}
}
FrameDecoder is an implementation of ChannelHandler which makes it easy to which deals with the fragmentation issue.
If null is returned, it means there's not enough data yet. FrameDecoder will call again when there is a sufficient amount of data.
If non-null is returned, it means the decode method has decoded a message successfully. FrameDecoder will discard the read part of its internal cumulative buffer. Please remember that you don't need to decode multiple messages. FrameDecoder will keep calling the decoder method until it returns null.
private void callDecode(ChannelHandlerContext context, Channel channel,ChannelBuffer cumulation, SocketAddress remoteAddress) throws Exception {while (cumulation.readable()) {int oldReaderIndex = cumulation.readerIndex();Object frame = decode(context, channel, cumulation);if (frame == null) {if (oldReaderIndex == cumulation.readerIndex()) {// Seems like more data is required.// Let us wait for the next notification.break;} else {// Previous data has been discarded.// Probably it is reading on.continue;}} else if (oldReaderIndex == cumulation.readerIndex()) {throw new IllegalStateException("decode() method must read at least one byte " +"if it returned a frame (caused by: " + getClass() + ")");}unfoldAndFireMessageReceived(context, remoteAddress, frame);}if (!cumulation.readable()) {this.cumulation = null;}}
If you are an adventurous person, you might want to try the ReplayingDecoder which simplifies the decoder even more. You will need to consult the API reference for more information though.
private void callDecode(ChannelHandlerContext context, Channel channel, ChannelBuffer cumulation, SocketAddress remoteAddress) throws Exception {while (cumulation.readable()) {int oldReaderIndex = checkpoint = cumulation.readerIndex();Object result = null;T oldState = state;try {result = decode(context, channel, replayable, state);if (result == null) {if (oldReaderIndex == cumulation.readerIndex() && oldState == state) {throw new IllegalStateException("null cannot be returned if no data is consumed and state didn't change.");} else {// Previous data has been discarded or caused state transition.// Probably it is reading on.continue;}}} catch (ReplayError replay) {// Return to the checkpoint (or oldPosition) and retry.int checkpoint = this.checkpoint;if (checkpoint >= 0) {cumulation.readerIndex(checkpoint);} else {// Called by cleanup() - no need to maintain the readerIndex// anymore because the buffer has been released already.}}if (result == null) {// Seems like more data is required.// Let us wait for the next notification.break;}if (oldReaderIndex == cumulation.readerIndex() && oldState == state) {throw new IllegalStateException("decode() method must consume at least one byte " +"if it returned a decoded message (caused by: " +getClass() + ")");}// A successful decodeunfoldAndFireMessageReceived(context, result, remoteAddress);if (!cumulation.readable()) {this.cumulation.set(null);replayable = ReplayingDecoderBuffer.EMPTY_BUFFER;}}}
这篇关于netty-time-Second Solution的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!