相关知识点:
[1] ChannelGroup是一个容纳打开的通道实例的线程安全的集合,方便我们统一施加操作。所以在使用的过程中能够将一些相关的Channel归类为一个有意义的集合。关闭的通道会自己主动从集合中移除。并且一个Channel能够属于多个ChannelGroup。常见的应用场景是 向一组通道广播消息;简化一组通道的关闭流程。

[2] 由于在Channel中流通的是ChannelBuffer (能够联系NIO ByteBuffer进行理解)。而在内部流水线中处理的可能是一个个对象,所以在收到或要发送到对端的时候就须要一个解码,编码的过程:在实际有意义的对象和字节数组间转换。
[3] 在client和服务器端流水线中handler运行顺序是不同的。在client中运行顺序和ChannelPipeline的添加顺序一致。而服务器端则恰好是相反的,这一点要注意,所以看到编解码类的位置是那样的。
详细代码:
TimeClient.java
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.ChannelFuture;
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 {
public static void main(String[] args) {
String host = "localhost";
int port = 8080; if(args.length == 2){
host = args[0];
port = Integer.parseInt(args[1]);
} ChannelFactory factory = new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(), Executors.newCachedThreadPool()); ClientBootstrap bootstrap = new ClientBootstrap(factory);
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(new TimeDecoder2(),
new TimeClientHandler4());
}
}); ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port)); //
future.awaitUninterruptibly();
if(!future.isSuccess()){
future.getCause().printStackTrace();
}
future.getChannel().getCloseFuture().awaitUninterruptibly();
factory.releaseExternalResources();
} }

TimeDecoder2.java

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

TimeClientHandler4.java

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
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 TimeClientHandler4 extends SimpleChannelHandler{
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
//the decoder put UnixTime obj,so get just what we need
UnixTime cur = (UnixTime)e.getMessage();
System.out.println(cur);
e.getChannel().close();
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
e.getCause().printStackTrace();
Channel c = e.getChannel();
c.close();
}
}

TimeServer.java

import java.net.InetSocketAddress;
import java.util.concurrent.Executors; import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.Channel;
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.group.ChannelGroup;
import org.jboss.netty.channel.group.ChannelGroupFuture;
import org.jboss.netty.channel.group.DefaultChannelGroup;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; public class TimeServer {
//[1]
public static ChannelGroup allChannels = new DefaultChannelGroup("time-server"); public static void main(String[] args) {
ChannelFactory factory = new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()); ServerBootstrap bootstrap = new ServerBootstrap(factory);
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
@Override
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(new TimeServerHandler2(),
new TimeEncoder());
}
}); bootstrap.setOption("reuseAddr", true);
bootstrap.setOption("child.tcpNoDelay", true);
bootstrap.setOption("child.keepAlive", true); Channel channel = bootstrap.bind(new InetSocketAddress(8080)); allChannels.add(channel);
//waitForShutdownCommand(); this is a imaginary logic:for instance
//when there is accepted connection we close this server ;
if(allChannels.size() >=2){
ChannelGroupFuture f = allChannels.close();
f.awaitUninterruptibly();
factory.releaseExternalResources();
}
}
}

TimeServerHandler2.java

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
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.ExceptionEvent;
import org.jboss.netty.channel.SimpleChannelHandler; public class TimeServerHandler2 extends SimpleChannelHandler{
@Override
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
TimeServer.allChannels.add(e.getChannel());
}
@Override
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
UnixTime time = new UnixTime((int) (System.currentTimeMillis() / 1000));
ChannelFuture f = e.getChannel().write(time);
f.addListener(ChannelFutureListener.CLOSE);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
e.getCause().printStackTrace();
Channel c = e.getChannel();
c.close();
}
}

TimeEncoder.java

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; public class TimeEncoder extends SimpleChannelHandler{
@Override
public void writeRequested(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
UnixTime time = (UnixTime)e.getMessage();
ChannelBuffer buf = ChannelBuffers.buffer(4);
buf.writeInt(time.getValue());
Channels.write(ctx, e.getFuture(), buf);
}
}

UnixTime.java

import java.util.Date;

public class UnixTime {
private int value;
public UnixTime(int value){
this.value = value;
}
public int getValue(){
return this.value;
}
public void setValue(int value){
this.value = value;
}
@Override
public String toString() {
//Allocates a Date object and initializes it to represent the specified number
//of milliseconds since the standard base time known as "the epoch",
//namely January 1, 1970, 00:00:00 GMT
return new Date(value * 1000L).toString();
}
}

最新文章

  1. 『.NET Core CLI工具文档』(十)dotnet-build
  2. ADO.NET常用对象
  3. Struts2 源码分析——核心机制
  4. C/C++中的getline函数总结:
  5. ubuntu挂载其他分区到/home下,将当前分区内容替换
  6. 算法第四版 在Eclipse中调用Algs4库
  7. 漫谈刑事辩护 z
  8. JAVA中“==”与equals()方法区别
  9. 百度UEditor编辑器使用教程与使用方法
  10. git 提交
  11. C++中的dynamic_cast和static_cast
  12. atitit.高级编程语言的特性 and 未来趋势与进化.doc
  13. java数据库编程之事务、视图、索引、备份、恢复
  14. CSS 换行问题white-space属性 window对象和global对象
  15. 【Shell脚本学习指南笔记】重定向文件描述符 2&gt;&amp;1
  16. Dynamics 365 CE的插件/自定义工作流活动中调用Web API示例代码
  17. 谈谈Java中的volatile(转载)
  18. CloudSim源代码学习——任务单元(Cloudlet)
  19. [Oracle][Standby][PDB]在PDB中修改参数,设置范围为 SPFILE,报 ORA-65099错误
  20. Python: PySide(PyQt)QMessageBox按钮显示中文

热门文章

  1. BZOJ 1260: [CQOI2007]涂色paint【区间DP】
  2. AJAX技术简介
  3. 把项目变成intellij idea和eclipse项目
  4. STL学习笔记(四) 迭代器
  5. poj 2987 Firing
  6. Codeforces Round #291 (Div. 2) D. R2D2 and Droid Army [线段树+线性扫一遍]
  7. 使用Sharesdk实现第三方平台登录(qq,新浪微博)
  8. Sql server 各版本下载链接
  9. ios实现下载图片的裁减和显示
  10. 【flyway】开源的数据库版本管理工具【migration】