相关知识点:
[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();
}
}

Netty实现时间服务演示样例的更多相关文章

  1. 一步一步跟我学习lucene(18)---lucene索引时join和查询时join使用演示样例

    了解sql的朋友都知道,我们在查询的时候能够採用join查询,即对有一定关联关系的对象进行联合查询来对多维的数据进行整理.这个联合查询的方式挺方便的.跟我们现实生活中的托人找关系类似,我们想要完毕一件 ...

  2. JDBC连接MySQL数据库及演示样例

    JDBC是Sun公司制定的一个能够用Java语言连接数据库的技术. 一.JDBC基础知识         JDBC(Java Data Base Connectivity,java数据库连接)是一种用 ...

  3. java 覆盖hashCode()深入探讨 代码演示样例

    java 翻盖hashCode()深入探讨 代码演示样例 package org.rui.collection2.hashcode; /** * 覆盖hashcode * 设计HashCode时最重要 ...

  4. 模式识别 - 处理多演示样例学习(MIL)特征(matlab)

    处理多演示样例学习(MIL)特征(matlab) 本文地址: http://blog.csdn.net/caroline_wendy/article/details/27206325 多演示样例学习( ...

  5. java并行调度框架封装及演示样例

    參考资料:  阿里巴巴开源项目 CobarClient  源代码实现. 分享作者:闫建忠 分享时间:2014年5月7日 ---------------------------------------- ...

  6. Java连接redis的使用演示样例

    Java连接redis的使用演示样例 Redis是开源的key-value存储工具,redis通经常使用来存储结构化的数据,由于redis的key能够包括String.hash.listset和sor ...

  7. Introspector(内省)简单演示样例 与 简单应用

    简单演示样例: package com.asdfLeftHand.test; import java.beans.BeanDescriptor; import java.beans.BeanInfo; ...

  8. libcurl使用演示样例

    简要说明:C++使用libcurl訪问"www.baidu.com".获取返回码和打印出http文件 /* * @ libcurl使用演示样例 * @ 2014.04.29 * @ ...

  9. 构造Scala开发环境并创建ApiDemos演示样例项目

    从2011年開始写Android ApiDemos 以来.Android的版本号也更新了非常多,眼下的版本号已经是4.04. ApiDemos中的样例也添加了不少,有必要更新Android ApiDe ...

随机推荐

  1. 【Luogu】P2015二叉苹果树(DP,DFS)

    题目链接 设f[i][j][k]表示给以i为根节点的子树分配j条可保留的树枝名额的时候,状态为k时能保留的最多苹果. k有三种情况. k=1:我只考虑子树的左叉,不考虑子树的右叉,此时子树能保留的最多 ...

  2. spring之生命周期

    1.容器中对的生命周期 spring可以管理 singleton作用域的bean的生命周期,spring可以精确地知道该bean何时被创建,何时被初始化完成,容器合适准备销毁该bean实例. spri ...

  3.  为什么上传文件的表单里要加个属性enctype----摘录

    上传文件的表单中<form>要加属性enctype="multipart/form-data",很多人只是死记硬背知道上传表单要这么写,知其然而不知其所以然.那到底为什 ...

  4. JQuery Mobile 的引用代码,以及在手机浏览器上字体太小的解决办法

    JQuery Mobile 的引用代码: <link rel="stylesheet" href="http://code.jquery.com/mobile/1. ...

  5. Failed building wheel for Twisted

    在安装scrapy框架的过程中,pip install scrapy 出现报错信息: building 'twisted.test.raiser' extension error: Microsoft ...

  6. elasticsearch入门使用(二) Mapping + field type字段类型

    Elasticsearch Reference [6.2] » Mapping 参考官方英文文档 https://www.elastic.co/guide/en/elasticsearch/refer ...

  7. (43)C#网络1 http

    一.HttpClient类 用于发送http请求,并接受请求的相应 (从4.5起开始可用) using System.Net.Http; 异步调用 HttpClient httpClient = ne ...

  8. python两个类之间变量和函数的调用

    1.class_a() class_b() 2.class_b使用class_a中的变量和函数 3.变量class_a中:class_a.num=... 函数class_b中:先实例化class_a( ...

  9. org.xml.sax.SAXParseException: 元素内容必须由格式正确的字符数据或标记组成,的错误问题

    当时在mapper其中的一个语句是case when ISNULL(b.c_truename) || LENGTH(TRIM(b.c_truename)) < 1 then b.c_ch_nam ...

  10. vueSSR渲染原理

    优点:利于搜索引擎,解决白屏问题,因为正常情况下在index.html文件中只有一个简单的标签,没有内容,不利于爬虫搜索 场景:交互少,数据多,例如新闻,博客,论坛类等 原理:相当于服务端前面加了一层 ...