package org.q.netty.time3;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
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.NioServerSocketChannelFactory;
public class TimeServer {
public static void main(String[] args) {
ChannelFactory factory = new NioServerSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool());
ServerBootstrap bootstrap = new ServerBootstrap(factory);
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(new TimeEncoder(), new TimeServerHandler());
}
});
bootstrap.setOption("child.tcpNoDelay", true);
bootstrap.setOption("child.keepAlive", true);
bootstrap.bind(new InetSocketAddress(9999));
}
}
package org.q.netty.time3;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.q.netty.model.UnixTime;
public class TimeServerHandler extends SimpleChannelHandler {
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
UnixTime time = new UnixTime((int)System.currentTimeMillis()/1000);
ChannelFuture future = e.getChannel().write(time);
future.addListener(ChannelFutureListener.CLOSE);
}
}
package org.q.netty.time3;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.q.netty.model.UnixTime;
public class TimeEncoder extends SimpleChannelHandler {
@Override
public void writeRequested(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
UnixTime time = (UnixTime)e.getMessage();
ChannelBuffer buffer = ChannelBuffers.buffer(4);
buffer.writeInt(time.getValue());
Channels.write(ctx, e.getFuture(), buffer);
}
}
package org.q.netty.time3;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
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) {
ClientBootstrap bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
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.time3;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.q.netty.model.UnixTime;
public class TimeClientHandler extends SimpleChannelHandler{
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
UnixTime time = (UnixTime)e.getMessage();
System.out.println(time);
e.getChannel().close();
}
}
package org.q.netty.time3;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.FrameDecoder;
import org.q.netty.model.UnixTime;
public class TimeDecoder extends FrameDecoder {
@Override
protected Object decode(ChannelHandlerContext ctx, Channel channel,
ChannelBuffer buffer) throws Exception {
if(buffer.readableBytes()<4) {
return null;
}
return new UnixTime(buffer.readInt());
}
}
An encoder overrides the writeRequested method to intercept a write request. Please note that the MessageEvent parameter here is the same type which was specified in messageReceived but they are interpreted differently. A ChannelEvent can be either an upstream or downstream event depending on the direction where the event flows. For instance, a MessageEvent can be an upstream event when called for messageReceived or a downstream event when called for writeRequested. Please refer to the API reference to learn more about the difference between a upstream event and a downstream event.
encoder重载了writeRequested方法来拦截写请求。writeRequested方法的MessageEvent参数和messageReceived中的MessageEvent类型是相同的,但是解释确实不同的。ChannelEvent根据数据流向可以是上传流事件,也可以是下传流事件。
Once done with transforming a POJO into a ChannelBuffer, you should forward the new buffer to the previous ChannelDownstreamHandler in the ChannelPipeline. Channels provides various helper methods which generates and sends a ChannelEvent. In this example, Channels.write(...) method creates a new MessageEvent and sends it to the previous ChannelDownstreamHandler in the ChannelPipeline.