上节介绍的是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. laravel基础课程---12、lavarel的ajax操作2(lavarel的ajax使用总结)

    laravel基础课程---12.lavarel的ajax操作2(lavarel的ajax使用总结) 一.总结 一句话总结: 比较简单:就是js请求ajax,然后控制器获取请求参数,返回数据即可 1. ...

  2. 分享知识-快乐自己:java 中的访问修饰符

    1):Java中的访问修饰符: Java面向对象的基本思想之一是封装细节并且公开接口.Java语言采用访问控制修饰符来控制类及类的方法和变量的访问权限,从而向使用者暴露接口,但隐藏实现细节. 访问控制 ...

  3. 微软面试题:鸡蛋从第N层及以上的楼层落下会摔破

    from:https://blog.csdn.net/qq_18425655/article/details/52326709   题目: 有一栋楼共100层,一个鸡蛋从第N层及以上的楼层落下来会摔破 ...

  4. eclipse如何在不联网的情况下引入dtd约束文件

    1. 获取dtd文件,解压 F:\Java配置文件\Mybatis\mybatis-3.3.0\mybatis-3.3.0.jar\org\apache\ibatis\builder\xml\ 路径下 ...

  5. 局域网扫描IP

    今天有朋友去面试,被问到一个“如何扫描局域网IP”的问题(即找出局域网中当前已使用的IP),朋友回答的不好,回来问我,我首先想到的就是使用ping命令将局域网可分配的IP地址逐个遍历一遍,能ping通 ...

  6. Could not load the "xxx.png" image referenced from a nib in the bundle with identifier "com.xxxx"

    打印台logs:  Could not load the "xxx.png" image referenced from a nib in the bundle with iden ...

  7. CodeForces - 884F :Anti-Palindromize(贪心&费用流)

    A string a of length m is called antipalindromic iff m is even, and for each i (1 ≤ i ≤ m) ai ≠ am - ...

  8. x264源代码分析-转

    相关说明: 1.     使用版本:  x264-cvs-2004-05-11 2.     这次的分析基本上已经将代码中最难理解的部分做了阐释,对代码的主线也做了剖析,如果这个主线理解了,就容易设置 ...

  9. The current .NET SDK does not support targeting .NET Core 2.2

    The current .NET SDK does not support targeting .NET Core 2.2 1. 奇怪的错误 最近遇到了一件奇怪的事, The current .NET ...

  10. VijosP1112:小胖的奇偶

    描述 huyichen和xuzhenyi在玩一个游戏:他写一个由0和1组成的序列. huyichen选其中的一段(比如第3位到第5位),问他这段里面有奇数个1还是偶数个1.xuzhenyi回答你的问题 ...