Netty(2)Echo
上节介绍的是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的更多相关文章
- netty写Echo Server & Client完整步骤教程(图文)
1.创建Maven工程 1.1 父节点的pom.xml代码(root pom文件) 1 <?xml version="1.0" encoding="UTF-8&qu ...
- Java Netty 4.x 用户指南
问题 今天,我们使用通用的应用程序或者类库来实现互相通讯,比如,我们经常使用一个 HTTP 客户端库来从 web 服务器上获取信息,或者通过 web 服务来执行一个远程的调用. 然而,有时候一个通用的 ...
- netty Getting Started--reference
reference from:http://docs.jboss.org/netty/3.1/guide/html/start.html 1.1. Before Getting Started 1.2 ...
- Netty In Action中国版 - 第二章:第一Netty程序
本章介绍 获得Netty4最新的版本号 设置执行环境,以构建和执行netty程序 创建一个基于Netty的server和client 拦截和处理异常 编制和执行Nettyserver和client 本 ...
- Netty 启动过程源码分析 (本文超长慎读)(基于4.1.23)
前言 作为一个 Java 程序员,必须知道Java社区最强网络框架-------Netty,且必须看过源码,才能说是了解这个框架,否则都是无稽之谈.今天楼主不会讲什么理论和概念,而是使用debug 的 ...
- User guide for Netty 4.x
Table of Contents Preface The Solution Getting Started Before Getting Started Writing a Discard Serv ...
- Netty 介绍
本指南对Netty 进行了介绍并指出其意义所在. 1. 问题 现在,我们使用适合一般用途的应用或组件来和彼此通信.例如,我们常常使用一个HTTP客户端从远程服务器获取信息或者通过web service ...
- Netty官方示例
一.DEMO 官方并没有使用Hello World来作为一个例子,而是采用RFC的DISCARD,这个协议定义了就是接收到请求后什么也不干. 第一步编写DiscardServerHandler类: p ...
- netty参考
前言 问题 现如今我们使用通用的应用程序或者类库来实现系统之间地互相访问,比如我们经常使用一个HTTP客户端来从web服务器上获取信息,或者通过web service来执行一个远程的调用. 然而,有时 ...
随机推荐
- UML中的6大关系详细说明
UML中的6大关系详细说明: 1.关联关系: 含义:类与类之间的连结,关联关系使一个类知道另外一个类的属性和方法:通常含有“知道”,“了解”的含义 体现:在C#中,关联关系是通过成员变量来实现的: 方 ...
- 2015推荐的Android框架
一.Guava Google的基于java1.6的类库集合的扩展项目,包括collections, caching, primitives support, concurrency libraries ...
- ubuntu 安装cuda 成功
洗洗睡了
- python处理时间汇总
1.将字符串的时间转换为时间戳 方法: a = "2013-10-10 23:40:00" 将其转换为时间数组 import time timeArray = time.strpt ...
- 查询oracle 数据库 SQL语句执行情况
1.查看总消耗时间最多的前10条SQL语句 select * from (select v.sql_id, v.child_number, v.sql_text, v.elapsed_time ...
- mysql数据库表分区详解(数量过大的数据库表通过分区提高查询速度)
这篇文章主要介绍了MySQL的表分区,例如什么是表分区.为什么要对表进行分区.表分区的4种类型详解等,需要的朋友可以参考下 一.什么是表分区通俗地讲表分区是将一大表,根据条件分割成若干个小表.mysq ...
- BOM——浏览器对象模型(Browser Object Model)
什么是BOM? BOM是Browser Object Model的缩写,简称浏览器对象模型 BOM提供了独立于内容而与浏览器窗口进行交互的对象 由于BOM主要用于管理窗口与窗口之间的通讯,因此其核心对 ...
- Polygon
用当前的笔绘制一个由两个或多个点(顶点)连接的多边形. BOOL Polygon( LPPOINT lpPoints, int nCount ); lpPoints 指向一个指定多边形顶点的点.数组中 ...
- Android如何解析json数组对象
import org.json.JSONArray; import org.json.JSONObject; //jsonData的数据格式:[{ "id": "27Jp ...
- win7 卸载ie10+ 重新安装ie8
烦恼: erp系统不支持高版本ie10+ 项目开发测试需要安装了高版本ie 项目结束,为了方便使用erp,决定卸载ie11,重新安装ie8 解决方法: 1.win+R打开运行命令,键入appwiz.c ...