Netty(1-1)Discard
一、DiscardServerHandler
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter; public class DiscardServerHandler extends ChannelInboundHandlerAdapter {//(1) @Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {//(2)
ByteBuf in = (ByteBuf) msg;
//discard the received data silently
in.release();//(3)
} @Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {//(4)
cause.printStackTrace();
ctx.close();
} }
1、DiscardServerHandler extends ChannelInboundHandlerAdapter。ChannelInboundHandlerAdapter是ChannelInboundHandler的实现。ChannelInboundHandler提供了很多event handler的方法,需要你自行覆盖。但是,你不需要自己实现它,只需要extends ChannelInboundHandlerAdapter即可。
2、覆盖channelRead(),当收到消息时,该方法会被调用,来自客户端的任何数据都会被接收到。本例,接收的消息类型是ByteBuf。
3、为了实现DISCARD PROTOCOL,该handler必须忽略掉接收到的消息。ByteBuf是reference-counted对象,必须被销毁,通过写release()。但是,如果该ByteBuffer,需要传递给下一个handler处理时,则不要release()。调用release()的场景:
1)、谁是最后使用者,谁负责释放
2)、如果有异常了,即ByteBuf没有成功传递到下一个Handler,一定要自行释放。
通常channelRead()类似如下实现:
try {
// Do something with msg
} finally {
ReferenceCountUtil.release(msg);
}
4、exceptionCaught(),由于I/O异常或者处理events时异常会调用该方法。多数情况下,该方法内应该实现
1)、logged(记录错误日志)
2)、关闭掉相关的channel。
当然,你可以在关闭该connection前,返回response消息给客户端。
二、DiscardServer
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j; /**
* Discards any incoming data
*/
@Slf4j
public class DiscardServer {
private int port; public DiscardServer(int port) {
this.port = port;
} public void run() throws InterruptedException {
EventLoopGroup bossGroup = new NioEventLoopGroup();//(1)
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
ServerBootstrap b = new ServerBootstrap();//(2)
b.group(bossGroup,workerGroup)
.channel(NioServerSocketChannel.class)//(3)
.childHandler(new ChannelInitializer<SocketChannel>() {//(4)
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new DiscardServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 128)//(5)
.childOption(ChannelOption.SO_KEEPALIVE, true);//(6)
//bind and start to accept incoming connections
ChannelFuture f = b.bind(port).sync();//(7)
log.info(DiscardServer.class.getName() + "started and listen on " + f.channel().localAddress());
//wait unit the server socket is closed.
//本例中,不会关闭,但以下能优雅关闭server
f.channel().closeFuture().sync();//(8)
//log.info("===================已关闭");
} finally {
workerGroup.shutdownGracefully();//(9)
bossGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws InterruptedException {
int port = 8080;
new DiscardServer(port).run();
}
}
1、NioEventLoopGroup是多线程的event loop,用于处理I/O操作。netty提供了多种EventLoopGroup,如:OioEventLoopGroup。服务端,建议使用2个NioEventLoopGroup。第一个,常叫做“boss”,接收connection,其实就是Acceptor线程池,建议线程数设置为1。第二个,常叫做“worker”,真正负责I/O读写操作的线程池,将connection注册到 该worker上,用于后续的Channel绑定。
public NioEventLoopGroup() {
this(0);
}
public NioEventLoopGroup(int nThreads) {
this(nThreads, (Executor) null);
}
2、ServerBootstrap是一个帮助类,对于Channel,直接写即可,如:.channel(NioServerSocketChannel.class)
3、使用NioServerSocketChannel接收connection
4、每来一个connection,则会创建一个Channel,并且该ChannelInitializer将会新增一个DiscardServerHandler实例到该Channel的ChannelPipeline。
5、socket自带参数,参考ChannelOption和ChannelConfig
6、option()用于NioServerSocketChannel接收connection。childOption()用于Channel
5、6参见https://www.jianshu.com/p/0bff7c020af2
7、以“异步方式”绑定server;sync()等待绑定的完成。
8、
1)关闭该Channel(断开connection) 并且,
2)获取该Channel的CloseFuture,通过阻塞当前线程直到完成。
9、关闭NioEventLoopGroup,并且释放掉所有资源
三、测试
使用telnet,
telnet localhost 8080

服务端没有任何动静,因为,没打印日志,且释放掉了。为了看得效果,修改DiscardServerHandler中的channelRead方法,如下:
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf in = (ByteBuf) msg;
try {
while (in.isReadable()) {//(1)
log.info("{}",(char)in.readByte());
System.out.flush();
}
} finally {
ReferenceCountUtil.release(msg);//(2)
}
}
然后,telnet
Microsoft Telnet> send s1
发送字符串 s1
Microsoft Telnet>
服务端收到:
11:32:52.533 [nioEventLoopGroup-3-1] s
11:32:52.535 [nioEventLoopGroup-3-1] 1
1、这个效率低下的while,可以替换成:
log.info(in.toString(io.netty.util.CharsetUtil.UTF_8));
telnet后,输出:11:36:04.363 [nioEventLoopGroup-3-1] s1
2、这里的release也可以使用in.release();
继续telnet测试,在windows下发送中文,服务器接收到的是乱码。但是在linux下执行:
[root@cent7-zuoys ~]# telnet 10.134.253.10 8080
Trying 10.134.253.10...
Connected to 10.134.253.10.
Escape character is '^]'.
遥远
服务器打印:11:46:56.333 [nioEventLoopGroup-3-3] 遥远
下一节,写netty client,代替telnet。
Netty(1-1)Discard的更多相关文章
- Netty学习笔记(四) 简单的聊天室功能之服务端开发
前面三个章节,我们使用了Netty实现了DISCARD丢弃服务和回复以及自定义编码解码,这篇博客,我们要用Netty实现简单的聊天室功能. Ps: 突然想起来大学里面有个课程实训,给予UDP还是TCP ...
- User guide for Netty 4.x
Table of Contents Preface The Solution Getting Started Before Getting Started Writing a Discard Serv ...
- netty参考
前言 问题 现如今我们使用通用的应用程序或者类库来实现系统之间地互相访问,比如我们经常使用一个HTTP客户端来从web服务器上获取信息,或者通过web service来执行一个远程的调用. 然而,有时 ...
- Netty4.0 用户指南
原文链接http://netty.io/wiki/user-guide-for-4.x.html 前言 Nowadays we use general purpose applications or ...
- Netty学习笔记(一) 实现DISCARD服务
官方那个给出的介绍是:Netty是由JBOSS提供的一个java开源框架.Netty提供异步的.事件驱动的网络应用程序框架和工具,用以快速开发高性能.高可靠性的网络服务器和客户端程序.然后我们简单理解 ...
- Netty(1-2)Discard Client
一.DiscardClientHandler import io.netty.buffer.ByteBuf; import io.netty.channel.ChannelFuture; import ...
- 【Netty】Netty的Hello World程序之Discard Server
一.有关Discard Server的说明 世界上最简单的协议(程序)不是“Hello, World!”而是Discard(丢弃).它是一种丢弃任何接收到的数据而没有任何响应的协议. 要实现丢弃协议, ...
- 从netty-example分析Netty组件续
上文我们从netty-example的Discard服务器端示例分析了netty的组件,今天我们从另一个简单的示例Echo客户端分析一下上个示例中没有出现的netty组件. 1. 服务端的连接处理,读 ...
- 从netty-example分析Netty组件
分析netty从源码开始 准备工作: 1.下载源代码:https://github.com/netty/netty.git 我下载的版本为4.1 2. eclipse导入maven工程. netty提 ...
随机推荐
- 一个坑:sql中问号(?)传参和 美元符号传参(${})的区别
? 可能会把参数加一对引号,不忽略前后空格? ${}是字符串拼接,好处是字符串前后的空格会被忽略... 但拼接有可能导致SQL注入
- 对python生成器特性使用的好例子
1.对序列进行分组的函数(摘自web.py源码utils.py文件中) def group(seq, size): """ Returns an iterator ove ...
- <opengl>使用glu绘制二次曲面
绘制二次曲面通常要以下四步: 1.首先我们创建一个二次方程状态对象 GLUquadricObj *m_pObj; //保存绘图模式.法线模式.法线朝向.纹理等信息 //创建二次方程状态对象 ...
- 每天一个linux命令(4):pwd命令
版权声明更新:2017-05-08博主:LuckyAlan联系:liuwenvip163@163.com声明:吃水不忘挖井人,转载请注明出处! 1 文章介绍 本文介绍了Linux下命令cd. 2 开发 ...
- 使用webdriver出现的问题:[18796:1808:0730/131103.313:ERROR:install_util.cc(600)] Failed to read HKLM\SOFTWARE\Policies\Google\Chrome\MachineLevelUserCloudPolicyEnrollmentToken: 系统找不到指定的文件。 (0x2) DevTools lis
1.注册表导致 [5956:4996:0710/155156.898:ERROR:install_util.cc(589)] Unable to create registry key HKLM\SO ...
- 为BindingList添加Sort
最近在优化WPF性能时, 发现在特定条件下BindingList比ObservableCollection性能更高, 因为它提供Disable/Enable 更改通知的方法.这样我们可以不需要很频繁的 ...
- Mysql常用命令行大全(一)
登录到mysql中,然后在mysql的提示符下运行下列命令,每个命令以分号结束. 1. 显示数据库列表. show databases; 缺省有两个数据库:mysql和test. mysql库存放着m ...
- 'xxx' declared `static' but never defined
'xxx' declared `static' but never defined [问题描述] uart.c文件中有函数read_sample的实现: [plain] view plain copy ...
- 【opencv学习笔记三】opencv3.4.0数据类型解释
opencv提供了多种基本数据类型,我们这里分析集中常见的类型.opencv的数据类型定义可以在D:\Program Files\opencv340\opencv\build\include\open ...
- javascript的三个函数
作为刚刚学习javascript的小白,最近阅读了额<Javascript Dom编程艺术>,其中有三个函数感觉很是有用,特此收藏. insertAfter函数:针对insertBefor ...