ChannelHandler是netty中核心, 因为看起来是这样。
我们看看4.0的ChannelHandler,就会发现其实不太一样。
public interface ChannelHandler {
/**
* Gets called before the {@link ChannelHandler} is added to the actual context.
*/
void beforeAdd(ChannelHandlerContext ctx) throws Exception;
/**
* Gets called after the {@link ChannelHandler} was added to the actual context.
*/
void afterAdd(ChannelHandlerContext ctx) throws Exception;
/**
* Gets called before the {@link ChannelHandler} is removed from the actual context.
*/
void beforeRemove(ChannelHandlerContext ctx) throws Exception;
/**
* Gets called after the {@link ChannelHandler} was removed from the actual context.
*/
void afterRemove(ChannelHandlerContext ctx) throws Exception;
/**
* Gets called if a {@link Throwable} was thrown.
*/
void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception;
/**
* Gets called if an user event was triggered.
*/
void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception;
}
这里略去一个注解的声明--Sharable
同时我没有列出对这个接口的注释。其实这个注释是3.5的还没更新。因为3.5到4.0还是有很大不同,我们来看看。
一个handler的接口,应该是定义我们应该处理一些什么情况见函数:
/**
* Gets called if an user event was triggered.
*/
void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception;
ChannelHandler 定义了事件接口。在仔细看这些事件接口,我们可以发现,都有一个ChannelHanderContext,注释中也说明,handler是注册到了ChannelHanderContext上的。所以,我们就看看ChannelHanderContext类吧。
public interface ChannelHandlerContext
extends AttributeMap, ChannelPropertyAccess,
ChannelInboundInvoker, ChannelOutboundInvoker {
...
}
这里的ChannelInboundInvoker接口基本上就是拥有通知Channel上的各种事件的能力,二ChannelOutboundInvoker则是具备了向管道外写数据,连接等功能。注意返回值都是ChannelFuture这就说明这些操作都是异步的。
总之ChannelOutboundInvoker是Channel,ChannelhandlerContext, ChannelPipeline的父接口。
好了,不要跑题了。对于ChannelHandlerContext来说,基本上就是对传输过程中的各个方面的管理器。包括ChannelHandler的注册销毁等等。
而对于ChannelHandler来说,有很多很多子接口,实现类。具体来说可通过ChannelHandlerType可以分为2类,4个type
public enum ChannelHandlerType {
STATE(0),
INBOUND(0),
OPERATION(1),
OUTBOUND(1);
final int direction; // 0 - up (inbound), 1 - down (outbound)
ChannelHandlerType(int direction) {
if (direction != 0 && direction != 1) {
throw new IllegalArgumentException("direction must be either 0 or 1");
}
this.direction = direction;
}
}
从这里可以看到,每个ChannelHander都是有方向性的。这里的方向性,也就是管道中inbound和outbound的意思。所以ChannelHander的两个子接口 ChannelOperationHandler 也就是outbound 和ChannelStateHandler 也就是inbound。围绕着in与out,又催生出子接口 ChannelOutboundHandler 和 ChannelInboundHandler。再下来,就是各种处理,基本不外乎 byte和message之间的转换。
这里有很多两个常用的Adapter,
- ChannelInboundMessageHandlerAdapter<T>
- ChannelInboundByteHandlerAdapter
对于ChannelInboundMessageHandlerAdapter<T>最主要的就是当消息到来时的处理,函数:
public void messageReceived(ChannelHandlerContext ctx, I msg) throws Exception;
将由用户去实现。
而对于ChannelInboundByteHandlerAdapter来说,函数和ChannelStateHandler的接口类似,被封装成:
/**
* Callback which will get notifed once the given {@link ByteBuf} received more data to read. What will be done
* with the data at this point is up to the implementation.
* Implementations may choose to read it or just let it in the buffer to read it later.
*/
public abstract void inboundBufferUpdated(ChannelHandlerContext ctx, ByteBuf in) throws Exception;
那么,handler是如何在事件发生时被调用的呢?
其实这应该是ChannelHandlerContext 告诉handler的,我们看下DefaultChannelHandlerContext就知道了。ChannelHandlerContext接口不具备了事件通知功能,也具备了管道的能力。
从DefaultChannelHandlerContext构造函数看
DefaultChannelHandlerContext(
DefaultChannelPipeline pipeline, EventExecutorGroup group,
DefaultChannelHandlerContext prev, DefaultChannelHandlerContext next,
String name, ChannelHandler handler)
最主要的几个成员变量就是这几个参数。从prev和next我们可以初步判断出这个ChannelHandlerContext 并不是单一出现的,而是linked的。
在来看pipeline,也有一个实现类DefaultChannelPipeline,构造函数为:
public DefaultChannelPipeline(Channel channel)
这也看得出这是对一个Channel的封装。再看成员变量,有
final DefaultChannelHandlerContext head;
private volatile DefaultChannelHandlerContext tail;
private final Map<String, DefaultChannelHandlerContext> name2ctx =
new HashMap<String, DefaultChannelHandlerContext>(4);
于是猜到最终的ChannelHandlerContext是在这里生成的,而且是链式的。
来看看我们最常用的函数 addFirst
@Override
public ChannelPipeline addFirst(String name, ChannelHandler handler) {
return addFirst(null, name, handler);
}
@Override
public ChannelPipeline addFirst(EventExecutorGroup group, final String name, ChannelHandler handler) {
final DefaultChannelHandlerContext nextCtx;
final DefaultChannelHandlerContext newCtx;
synchronized (this) {
checkDuplicateName(name);
nextCtx = head.next;
newCtx = new DefaultChannelHandlerContext(this, group, head, nextCtx, name, handler);
if (!newCtx.channel().isRegistered() || newCtx.executor().inEventLoop()) {
addFirst0(name, nextCtx, newCtx);
return this;
}
}
// Run the following 'waiting' code outside of the above synchronized block
// in order to avoid deadlock
newCtx.executeOnEventLoop(new Runnable() {
@Override
public void run() {
synchronized (DefaultChannelPipeline.this) {
checkDuplicateName(name);
addFirst0(name, nextCtx, newCtx);
}
}
});
return this;
}
private void addFirst0(
final String name, DefaultChannelHandlerContext nextCtx, DefaultChannelHandlerContext newCtx) {
callBeforeAdd(newCtx);
if (nextCtx != null) {
nextCtx.prev = newCtx;
}
head.next = newCtx;
if (tail == head) {
tail = newCtx;
}
name2ctx.put(name, newCtx);
callAfterAdd(newCtx);
}
这里基本就是对链表的处理了。DefaultChannelHandlerContext中还定义了一些事件任务。这些任务都是在EventLoop中提交的。使用EventExecutor。这些事件是用来通知链上的下一个ChannelHandlerContext,具体是什么需要看handler的方向了。
至此,ChannelHandler就差不多了,接下来该看看EventLoop是如何工作的了。
分享到:
相关推荐
netty4.0 关于buffe
Netty4.0全部jar包.开发时候只需要倒入总的哪一个netty4.0.jar就行了 后缀为resources.jar的全部是源码。 简单的代码例子在netty-example-resources.jar里面。
Netty (netty-netty-4.0.56.Final.tar.gz)是一个 NIO 客户端服务器框架,可以快速轻松地开发协议服务器和客户端等网络应用程序。它极大地简化和流线了网络编程,例如 TCP 和 UDP 套接字服务器。 “快速和简单”并...
NULL 博文链接:https://bijian1013.iteye.com/blog/2340636
描述文档请看我的个人博客:www.mesoftware.cn
NIO socket开发,netty4.0工具包。
Springboot2.0.8集成 netty4 ,使用protobuf作为ping的数据交换,比json更加的小巧,占用数据量更小,可用于任何第三方应用做心跳监控。 已完成功能: - 客户端授权验证(基于protoBuff) - 心跳检测(基于protoBuff) ...
Netty4.0实现http服务,客户端通过http请求,服务器进行业务处理,返回响应,交互采用json格式
netty4.0.45jar包socket和http工具包,公司最近开发一个保险项目,用到socket,经过公司10个以上项目验证,该版本的netty4.0.45相当稳定,可以在生产环境上使用。
NULL 博文链接:https://bijian1013.iteye.com/blog/2340632
Netty4.0.54英文版API文档,与官网中文档内容一致,方便用户在离线环境下,开发Netty
Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序dsf。...netty, 4.0.28, Final, jar包, 含源码
赠送jar包:netty-handler-4.1.73.Final.jar; 赠送原API文档:netty-handler-4.1.73.Final-javadoc.jar; 赠送源代码:netty-handler-4.1.73.Final-sources.jar; 赠送Maven依赖信息文件:netty-handler-4.1.73....
包含javadoc,jar 两个文件夹。 doc中是文档资料。 jar是源码及常用例子,均好源码,好使。
netty4.0 各种应用类型的demo源码 比较全
Netty project - an event-driven asynchronous network application framework http://netty.io/
Netty官方4.0.42版jar包
netty 4.0版本
Netty是一个异步事件驱动的网络应用程序框架,主要用于快速开发可维护的高性能协议服务器和客户端。它基于Java NIO进行设计,因此提供了高层次的抽象和简化的API,使得开发者可以更加方便地构建网络应用。 Netty在...
多种数据访Netty自带的拆包解包,异常检测等机制让你从NIO的繁重细节中脱离出来,让你只需要关心业务逻辑 Netty解决了JDK的很多包括空轮询在内的bug Netty底层对线程,selector做了很多细小的优化,精心设计的...