1. 老规矩, 引入我们喜闻乐见的maven依赖

 <dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.6.Final</version>
</dependency>

2. 服务端

  2.1: 服务端引导类:

 public class EchoServer {

     private int port;

     private EchoServer(int port) {
this.port = port;
} private void start() throws Exception {
System.out.println("Echo Server Start");
EventLoopGroup group = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();
b.group(group)
.channel(NioServerSocketChannel.class)
.localAddress(new InetSocketAddress(port))
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new EchoOutboundHandler1());
ch.pipeline().addLast(new EchoOutboundHandler2()); ch.pipeline().addLast(new EchoInboundHandler1());
ch.pipeline().addLast(new EchoInboundHandler2());
}
});
ChannelFuture f = b.bind().sync();
System.out.println("Server Start Listen At: " + port);
f.channel().closeFuture().sync();
} finally {
group.shutdownGracefully();
}
} public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new EchoServer(port).start();
}
}

  2.2 EchoOutboundHandler1

 public class EchoInboundHandler1 extends ChannelInboundHandlerAdapter {

     @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
// 读取msg中的数据
ByteBuf result = (ByteBuf) msg;
byte[] bytes = new byte[result.readableBytes()];
result.readBytes(bytes);
String resultStr = new String(bytes);
System.out.println("Server Received: " + resultStr + ": Inbound 1 Is OK"); // 处理完msg中的数据后往msg中重新存放新的数据继续传递
result.writeBytes(resultStr.getBytes());
ctx.fireChannelRead(result);
} }

  2.3 EchoInboundHandler2

 public class EchoInboundHandler2 extends ChannelInboundHandlerAdapter {

     @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
// 读取msg中的数据
ByteBuf result = (ByteBuf) msg;
byte[] bytes = new byte[result.readableBytes()];
result.readBytes(bytes);
String resultStr = new String(bytes);
System.out.println("Server Received: " + resultStr + ": Inbound 2 Is OK"); // 处理完msg中的数据后往msg中重新存放新的数据继续传递
result.writeBytes(resultStr.getBytes());
ctx.write(result);
} }

  2.4 EchoOutboundHandler2

 public class EchoOutboundHandler2 extends ChannelOutboundHandlerAdapter {

     @Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
// 读取msg中的数据
ByteBuf result = (ByteBuf) msg;
byte[] bytes = new byte[result.readableBytes()];
result.readBytes(bytes);
String resultStr = new String(bytes);
System.out.println("Server Received: " + resultStr + ": Outbound 2 Is OK"); // 处理完msg中的数据后往msg中重新存放新的数据继续传递
result.writeBytes(resultStr.getBytes());
ctx.write(result);
}
}

  2.5 EchoOutboundHandler1

 public class EchoOutboundHandler1 extends ChannelOutboundHandlerAdapter {

     @Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
// 读取msg中的数据
ByteBuf result = (ByteBuf) msg;
byte[] bytes = new byte[result.readableBytes()];
result.readBytes(bytes);
String resultStr = new String(bytes);
System.out.println("Server Received: " + resultStr + ": Outbound 1 Is OK"); // 处理完msg中的数据后往msg中重新存放新的数据继续传递
result.writeBytes(resultStr.getBytes());
ctx.write(result);
ctx.flush();
}
}

3. 客户端

 public class EchoClient {

     private String host;
private int port; private EchoClient(String host, int port) {
this.host = host;
this.port = port;
} private void start() throws Exception {
System.out.println("Echo Client Start");
EventLoopGroup group = new NioEventLoopGroup();
try {
Bootstrap b = new Bootstrap();
b.group(group)
.channel(NioSocketChannel.class)
.remoteAddress(new InetSocketAddress(host, port))
.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new EchoClientHandler());
}
});
ChannelFuture f = b.connect().sync();
System.out.println("Server Client Listen IP: [" + host + ":" + port + "]");
f.channel().closeFuture().sync();
} finally {
group.shutdownGracefully();
}
} public static void main(String[] args) throws Exception {
String host = "127.0.0.1";
int port = 8080;
int len = 2;
if (args.length == len) {
host = args[0];
port = Integer.parseInt(args[1]);
}
new EchoClient(host, port).start();
} }
 public class EchoClientHandler extends ChannelInboundHandlerAdapter {

     @Override
public void channelActive(ChannelHandlerContext ctx) {
ctx.writeAndFlush(Unpooled.copiedBuffer("Netty Rocks!", CharsetUtil.UTF_8));
} @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
// 读取msg中的数据
ByteBuf result = (ByteBuf) msg;
byte[] bytes = new byte[result.readableBytes()];
result.readBytes(bytes);
String resultStr = new String(bytes);
System.out.println("Echo Client Received Is OK: " + resultStr);
ctx.close();
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
}

4. 结果:

  服务端:

  客户端:

5. 注意事项:

5.1. ChannelInboundHandler之间的传递, 通过调用 ctx.fireChannelRead(msg) 实现; 调用ctx.write(msg) 将传递到ChannelOutboundHandler

5.2. ctx.write()方法执行后, 需要调用flush()方法才能令它立即执行

5.3. ChannelOutboundHandler 在注册的时候需要放在最后一个ChannelInboundHandler之前, 否则将无法传递到ChannelOutboundHandler

关于netty的多个handler链式模式的更多相关文章

  1. JavaScript 链式结构序列化详解

    一.概述 在JavaScript中,链式模式代码,太多太多,如下: if_else: if(...){ //TODO }else if(...){ //TODO }else{ //TODO } swi ...

  2. jQuery链式操作[转]

    用过jQuery的朋友都知道他强大的链式操作,方便,简洁,易于理解,如下 $("has_children").click(function(){ $(this).addClass( ...

  3. javascript实现数据结构:线性表--线性链表(链式存储结构)

    上一节中, 线性表的顺序存储结构的特点是逻辑关系上相邻的两个元素在物理位置上也相邻,因此可以随机存取表中任一元素,它的存储位置可用一个简单,直观的公式来表示.然后,另一方面来看,这个特点也造成这种存储 ...

  4. 用php实现一个简单的链式操作

    最近在读<php核心技术与最佳实践>这本书,书中第一章提到用__call()方法可以实现一个简单的字符串链式操作,比如,下面这个过滤字符串然后再求长度的操作,一般要这么写: strlen( ...

  5. C#用链式方法表达循环嵌套

    情节故事得有情节,不喜欢情节的朋友可看第1版代码,然后直接跳至“三.想要链式写法” 一.起缘 故事缘于一位朋友的一道题: 朋友四人玩LOL游戏.第一局,分别选择位置:中单,上单,ADC,辅助:第二局新 ...

  6. 由表单验证说起,关于在C#中尝试链式编程的实践

    在web开发中必不可少的会遇到表单验证的问题,为避免数据在写入到数据库时出现异常,一般比较安全的做法是前端会先做一次验证,通过后把数据提交到后端再验证一次,因为仅仅靠前端验证是不安全的,有太多的htt ...

  7. 如何写 JS 的链式调用 ---》JS 设计模式《----方法的链式调用

    1.以$ 函数为例.通常返回一个HTML元素或一个元素集合. 代码如下: function $(){ var elements = []; ;i<arguments.length;i++){ v ...

  8. iOS 链式编程探索(Masonry)

    看了几篇关于链式编程的文章,还是理解的不透彻,我想这可能是因为我自己对block掌握的不熟练. 我已经明白了,所以,和大家分享一下我的理解!如有问题,麻烦大家指出! 直接看代码吧!关键的注释都有. 我 ...

  9. jQuery插件编写及链式编程模型小结

    JQuery极大的提高了我们编写JavaScript的效率,让我们可以愉快的编写代码,做出各种特效.大多数情况下,我们都是使用别人开发的JQuery插件,今天我们就来看看如何把我们常用的功能做出JQu ...

随机推荐

  1. ThinkPHP __construct和_initialize的使用

    ThinkPHP框架中的__construct和_initialize的使用 父类(PlatformController.class.php): class PlatformController ex ...

  2. list如何remove

    http://blog.sina.com.cn/s/blog_621b6f0e0100s5n5.html 在java中对list进行操作很频繁,特别是进行list启遍历,这些操作我们都会,也很熟悉,但 ...

  3. 最近公共祖先(Least Common Ancestors)

    题意: 给定一棵有根树T,给出若干个查询lca(u, v)(通常查询数量较大),每次求树T中两个顶点u和v的最近公共祖先,即找一个节点,同时是u和v的祖先,并且深度尽可能大(尽可能远离树根).通常有以 ...

  4. POJ 1062 【带约束的最短路问题】

    中文题题意不写. 建图: 我自己想到的建图方式是把每个物品看作两个点,编号分别是i和i+n,然后每个物品两个点之间边的权值是物品本身的价值.然后从第i个点往外连边,目标是可替代品顶点编号较小的点,权值 ...

  5. Codeforces 920G(二分+容斥)

    题意: 定义F(x,p)表示的是一个数列{y},其中gcd(y,p)=1且y>x 给出x,p,k,求出F(x,p)的第k项 x,p,k<=10^6 分析: 很容易想到先二分,再做差 然后问 ...

  6. 七天从零基础学习android(2)--第一个安卓程序

    在环境配置的那一部分,已经把基础的环境配置好了,接下来应该实现第一个安卓程序,就是著名的hello world 先在avd里面新建一个虚拟机,并且启动它 然后该虚拟机器能够在eclipse上正常识别 ...

  7. 携程Apollo(阿波罗)配置中心Spring Boot迁移日志组件,使用配置中心进行管理的思路

    说明: 1.Spring Boot项目默认使用logback进行日志管理 2.logback在启动时默认会自动检查是否有logback.xml文件,如果有时会有限加载这个文件. 3.那么如果是用配置中 ...

  8. 静态网页怎样实现动态交互?-JavaScript

    在Html基础上,javascript能够开发交互式web网页.javascript的出现使得网页和用户之间实现了一种实时性的.动态的.交互性的关系,javascript短小精悍,又是在客户机上执行的 ...

  9. 分享一个检测用户是否用手机(Mobile)访问网站的 PHP 类

    有一个基于MIT License协议开源的PHP程序 http://code.google.com/p/php-mobile-detect/ 程序就是一个文件,下载之后直接引用就可以. 使用方法: & ...

  10. mysql数据库优化之表的设计和慢查询定位

    一.数据库优化包含的方面 数据库优化是一种综合性的技术.并非通过某一种方式让数据库效率提高非常多.而是通过多方面的提高.从而使得数据库性能提高. 主要包含: 1.表的设计合理化(3范式) 2.给表加入 ...