上节介绍的是discard协议,即不给客户端返回消息。本节主要说下,echo协议,即服务端收到消息后原样返回给客户端。

为了实现此需求,只需要在DiscardServerHandler中重写channelRead()方法,即可。如下:

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf in = (ByteBuf) msg;
log.info("接收并原样返回:{}",in.toString(io.netty.util.CharsetUtil.UTF_8)); ctx.write(msg);//(1)
ctx.flush();//(2)
}

1、ChannelHandlerContext对象提供了很多方法,如:

ctx.read();
ctx.write();
ctx.flust();
ctx.channel();
ctx.pipeline();
ctx.alloc();
ctx.close();
ctx.connect();
ctx.disconnect();

注意,我们这里没有release 接收到的消息,不像discard例子那样。因为,当消息写到物理网络中后,netty才会在自动release

在channelRead方法内的最后,加入in.release();即

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf in = (ByteBuf) msg;
log.info("接收并原样返回:{}",in.toString(io.netty.util.CharsetUtil.UTF_8)); ctx.write(msg);//(1)
ctx.flush();//(2)
in.release();
}

则报异常:io.netty.util.IllegalReferenceCountException: refCnt: 0, decrement: 1

因此,不能在server端的channelRead方法内加入in.release()。

当ctx.flush(msg)后,可以在channelReadComplete()方法中release。

2、ctx.write(object)并不会将消息写到物理网络中,而是在内部buffer中的,需要使用ctx.flush()来写入到物理网络中。当然,也可以使用ctx.writeAndFlush(msg)代替。

-----telnet测试:

客户端:

[root@cent7-zuoys ~]# telnet 10.134.253.10 8080
Trying 10.134.253.10...
Connected to 10.134.253.10.
Escape character is '^]'.
遥远2
遥远2

服务端:16:22:12.636 [nioEventLoopGroup-3-1] 接收并原样返回:遥远2

-----client测试:

@Slf4j
public class EchoClientHandler extends SimpleChannelInboundHandler<Object> {
private ByteBuf content;
private ChannelHandlerContext ctx; @Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
this.ctx = ctx;
//content = ctx.alloc().directBuffer(EchoClient.SIZE).writeZero(EchoClient.SIZE);
content = ctx.alloc().directBuffer(EchoClient.SIZE).writeBytes("遥远2".getBytes(CharsetUtil.UTF_8));
//发送以上消息
generatTraffic();
} @Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
content.release();
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf in = (ByteBuf) msg;
log.info("接收消息:{}"
,in.toString(io.netty.util.CharsetUtil.UTF_8));
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
//*************************自定义方法
private void generatTraffic() {
//flush the outbound buffer to the socket.
//once flushed,generate the same amount of traffic again.
ByteBuf buf = content.retainedDuplicate();
ctx.writeAndFlush(buf).addListener(trafficGenerator);
//Console.log((char)buf.readByte());
log.info("发送消息:{}",buf.toString(io.netty.util.CharsetUtil.UTF_8));
}
private final ChannelFutureListener trafficGenerator = new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (future.isSuccess()) {
log.info("success!");
} else {
future.cause().printStackTrace();
future.channel().close();
}
}
};
}

红字部分,为修改的。在channelRead0方法中,之前是空的,现在是因为,服务端返回消息了,需要在此处接收。

运行结果:

客户端:

16:50:42.443 [nioEventLoopGroup-2-1] success!
16:50:42.446 [nioEventLoopGroup-2-1] 发送消息:遥远2
16:50:42.461 [nioEventLoopGroup-2-1] 接收消息:遥远2

服务端:16:50:42.456 [nioEventLoopGroup-3-1] 接收并原样返回:遥远2


SimpleChannelInboundHandler 与 ChannelInboundHandlerAdapter区别:

服务端使用ChannelInboundHandlerAdapter,客户端使用SimpleChannelInboundHandler 。

因为ChannelInboundHandlerAdapter,在channelRead()内不能release。而SimpleChannelInboundHandler 自动release。

Netty(2)Echo的更多相关文章

  1. netty写Echo Server & Client完整步骤教程(图文)

    1.创建Maven工程 1.1 父节点的pom.xml代码(root pom文件) 1 <?xml version="1.0" encoding="UTF-8&qu ...

  2. Java Netty 4.x 用户指南

    问题 今天,我们使用通用的应用程序或者类库来实现互相通讯,比如,我们经常使用一个 HTTP 客户端库来从 web 服务器上获取信息,或者通过 web 服务来执行一个远程的调用. 然而,有时候一个通用的 ...

  3. netty Getting Started--reference

    reference from:http://docs.jboss.org/netty/3.1/guide/html/start.html 1.1. Before Getting Started 1.2 ...

  4. Netty In Action中国版 - 第二章:第一Netty程序

    本章介绍 获得Netty4最新的版本号 设置执行环境,以构建和执行netty程序 创建一个基于Netty的server和client 拦截和处理异常 编制和执行Nettyserver和client 本 ...

  5. Netty 启动过程源码分析 (本文超长慎读)(基于4.1.23)

    前言 作为一个 Java 程序员,必须知道Java社区最强网络框架-------Netty,且必须看过源码,才能说是了解这个框架,否则都是无稽之谈.今天楼主不会讲什么理论和概念,而是使用debug 的 ...

  6. User guide for Netty 4.x

    Table of Contents Preface The Solution Getting Started Before Getting Started Writing a Discard Serv ...

  7. Netty 介绍

    本指南对Netty 进行了介绍并指出其意义所在. 1. 问题 现在,我们使用适合一般用途的应用或组件来和彼此通信.例如,我们常常使用一个HTTP客户端从远程服务器获取信息或者通过web service ...

  8. Netty官方示例

    一.DEMO 官方并没有使用Hello World来作为一个例子,而是采用RFC的DISCARD,这个协议定义了就是接收到请求后什么也不干. 第一步编写DiscardServerHandler类: p ...

  9. netty参考

    前言 问题 现如今我们使用通用的应用程序或者类库来实现系统之间地互相访问,比如我们经常使用一个HTTP客户端来从web服务器上获取信息,或者通过web service来执行一个远程的调用. 然而,有时 ...

随机推荐

  1. 一次php脚本出现段错误(Segment fault)的经历

    今天在一台新服务器上cli运行一个php脚本,出现了Segment fault错误,第一感觉应该是某个扩展安装有问题 这段php代码是调用soap接口,查看soap扩展没啥问题,一时不知道是啥原因. ...

  2. Java常用类Date、Calendar、SimpleDateFormat详解

    Date类 java.util 包提供了 Date 类来封装当前的日期和时间,Date 类提供两个构造函数来实例化 Date 对象 第一个构造函数使用当前日期和时间来初始化对象   Date( ) 第 ...

  3. 如何解决GBK的编码的文件中的中文转换成为UTF-8编码的文件而且不乱码

    首先我们必须明确一点,为什么正常转换会乱码? 因为我们的数据写入是GBK写入的,然后展示的话是按照文件保存形势展示的,前面保存形势是GBK,一致,所以不乱码,而后面将保存形势变成了UTF-8,但是写入 ...

  4. linux 进程学习笔记-named pipe (FIFO)命名管道

    与“无名管道”不同的是,FIFO拥有一个名称来标志它,所谓的名称实际上就是一个路径,比如“/tmp/my_fifo”,其对应到磁盘上的一个管道文件,如果我们用file命令来查看其文件类型的话,会得到如 ...

  5. The Django Book 2.0--中文版

    Table of contents 2.0, English -> Chinese 第一章:介紹Django阅读 01 第二章 入门阅读 02 第三章 视图和URL配置阅读 03 第四章:模版阅 ...

  6. docker安装与操作

    准备和安装 1.到这个路径下下载docker engine: https://get.docker.com/rpm/1.7.1/centos-7/RPMS/x86_64/docker-engine-1 ...

  7. 洛谷P3205合唱队——区间DP

    题目:https://www.luogu.org/problemnew/show/P3205 枚举点,分类为上一个区间的左端点或右端点,满足条件便+=即可: 注意不要重复(当l=2时). 代码如下: ...

  8. POJ2828(插队问题)

    Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 17077   Accepted: 8466 Desc ...

  9. [spoj694&spoj705]New Distinct Substrings(后缀数组)

    题意:求字符串中不同子串的个数. 解题关键:每个子串一定是某个后缀的前缀,那么原问题等价于求所有后缀之间的不相同的前缀的个数. 1.总数减去height数组的和即可. 注意这里height中为什么不需 ...

  10. gcc -frandom-seed

    -frandom-seed=string This option provides a seed that GCC uses when it would otherwise use random nu ...