1.Channel
channel 是负责数据读,写的对象,有点类似于老的io里面的stream,他和stream的区别,channel是双向的
既可以write 也可以read,而stream要分outstream和inputstream。而且在NIO中用户不应该直接从channel中读写数据,
而是应该通过buffer,通过buffer再将数据读写到channel中。
一个channel 可以提供给用户下面几个信息
(1)channel的当前状态,比如open 还是closed
(2)ChannelConfig对象,表示channel的一些参数,比如bufferSize
(3)channel支持的所有i/o操作(比如read,write,connect.bind)以及ChannelPipeLine(下面解释)
2.ChannelConfig
channel的参数,以Map 数据结构来存储
3.ChannelEvent
ChannelEvent广义的认为Channel相关的事件,他是否分Upstream events和downstream events两大块,这里需要注意的,让是server为
主体的话,从client的数据到server的过程是Upstream;而server到client的数据传输过程叫downstream;而如果以client为主体
的话,从server到client的过程对client来说是Upstream,而client到server的过程对client来说就是downstream。
Upstream events包括:
messageReceived:信息被接受时 ---MessageEvent
exceptionCaught:产生异常时 ---ExceptionEvent
channelOpen:channel被开启时 ---ChannelStateEvent
channelClosed:channel被关闭时 ---ChannelStateEvent
channelBound:channel被开启并准备去连接但还未连接上的时候 ---ChannelStateEvent
channelUnbound:channel被开启不准备去连接时候 ---ChannelStateEvent
channelConnected:channel被连接上的时候 ---ChannelStateEvent
channelDisconnected:channel连接断开的时候 ---ChannelStateEvent
channelInterestChanged:Channel的interestOps被改变的时候 ------ChannelStateEvent
writeComplete:写到远程端完成的时候 --WriteCompletionEvent
Downstream events包括:
write:发送信息给channel的时候 --MessageEvent
bind:绑定一个channel到指定的本地地址 --ChannelStateEvent
unbind:解除当前本地端口的绑定--ChannelStateEvent
connect:将channel连接到远程的机 --ChannelStateEvent
disconnect:将channel与远程的机连接断开 --ChannelStateEvent
close:关闭channel --ChannelStateEvent
需要注意的是,这里没有open event,这是因为当一个channel被channelFactory创建的话,channel总是已经被打开了。
此外还有两个事件类型是当父channel存在子channel的情况
childChannelOpen:子channel被打开 ---ChannelStateEvent
childChannelClosed:子channel被关闭 ---ChannelStateEvent
4.ChannelHandler
channel是负责传送数据的载体,那么数据肯定需要根据要求进行加工处理,那么这个时候就用到ChannelHandler
不同的加工可以构建不同的ChannelHandler,然后放入ChannelPipeline中
此外需要有ChannelEvent触发后才能到达ChannelHandler,因此根据event不同有下面两种的sub接口ChannelUpstreamHandler
和ChannelDownstreamHandler。
一个ChannelHandler通常需要存储一些状态信息作为判断信息,常用做法定义一个变量
比如
public class DataServerHandler extends {@link SimpleChannelHandler} {
*
<b>private boolean loggedIn;</b>
*
{@code @Override}
public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
{@link Channel} ch = e.getChannel();
Object o = e.getMessage();
if (o instanceof LoginMessage) {
authenticate((LoginMessage) o);
<b>loggedIn = true;</b>
} else (o instanceof GetDataMessage) {
if (<b>loggedIn</b>) {
ch.write(fetchSecret((GetDataMessage) o));
} else {
fail();
}
}
}
...
}
// Create a new handler instance per channel.
// See {@link Bootstrap#setPipelineFactory(ChannelPipelineFactory)}.
public class DataServerPipelineFactory implements {@link ChannelPipelineFactory} {
public {@link ChannelPipeline} getPipeline() {
return {@link Channels}.pipeline(<b>new DataServerHandler()</b>);
}
}
除了这种,每个ChannelHandler都可以从ChannelHandlerContext中获取或设置数据,那么下面的做法就是利用ChannelHandlerContext
设置变量
{@code @Sharable}
public class DataServerHandler extends {@link SimpleChannelHandler} {
*
{@code @Override}
public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
{@link Channel} ch = e.getChannel();
Object o = e.getMessage();
if (o instanceof LoginMessage) {
authenticate((LoginMessage) o);
<b>ctx.setAttachment(true)</b>;
} else (o instanceof GetDataMessage) {
if (<b>Boolean.TRUE.equals(ctx.getAttachment())</b>) {
ch.write(fetchSecret((GetDataMessage) o));
} else {
fail();
}
}
}
...
}
public class DataServerPipelineFactory implements {@link ChannelPipelineFactory} {
*
private static final DataServerHandler <b>SHARED</b> = new DataServerHandler();
*
public {@link ChannelPipeline} getPipeline() {
return {@link Channels}.pipeline(<b>SHARED</b>);
}
}
这两种做法还是有区别的,上面的变量做法,每个new的handler 对象,变量是不共享的,而下面的ChannelHandlerContext是共享的
如果需要不同的handler之间共享数据,那怎么办,那就用ChannelLocal
例子:
public final class DataServerState {
*
<b>public static final {@link ChannelLocal}<Boolean> loggedIn = new {@link ChannelLocal}<Boolean>() {
protected Boolean initialValue(Channel channel) {
return false;
}
}</b>
...
}
*
{@code @Sharable}
public class DataServerHandler extends {@link SimpleChannelHandler} {
*
{@code @Override}
public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
Channel ch = e.getChannel();
Object o = e.getMessage();
if (o instanceof LoginMessage) {
authenticate((LoginMessage) o);
<b>DataServerState.loggedIn.set(ch, true);</b>
} else (o instanceof GetDataMessage) {
if (<b>DataServerState.loggedIn.get(ch)</b>) {
ctx.getChannel().write(fetchSecret((GetDataMessage) o));
} else {
fail();
}
}
}
...
}
*
// Print the remote addresses of the authenticated clients:
{@link ChannelGroup} allClientChannels = ...;
for ({@link Channel} ch: allClientChannels) {
if (<b>DataServerState.loggedIn.get(ch)</b>) {
System.out.println(ch.getRemoteAddress());
}
}
</pre>
5.ChannelPipeline
channelPipeline是一系列channelHandler的集合,他参照J2ee中的Intercepting Filter模式来实现的,
让用户完全掌握如果在一个handler中处理事件,同时让pipeline里面的多个handler可以相互交互。
Intercepting Filter:http://java.sun.com/blueprints/corej2eepatterns/Patterns/InterceptingFilter.html
对于每一个channel都需要有相应的channelPipeline,当为channel设置了channelPipeline后就不能再为channel重新设置
channelPipeline。此外建议的做法的通过Channels 这个帮助类来生成ChannelPipeline 而不是自己去构建ChannelPipeline
通常pipeLine 添加多个handler,是基于业务逻辑的
比如下面
{@link ChannelPipeline} p = {@link Channels}.pipeline();
p.addLast("1", new UpstreamHandlerA());
p.addLast("2", new UpstreamHandlerB());
p.addLast("3", new DownstreamHandlerA());
p.addLast("4", new DownstreamHandlerB());
p.addLast("5", new SimpleChannelHandler());
upstream event 执行的handler按顺序应该是 125
downstream event 执行的handler按顺序应该是 543
SimpleChannelHandler 是同时实现了 ChannelUpstreamHandler和ChannelDownstreamHandler的类
上面只是具有逻辑,如果数据需要通过格式来进行编码的话,那需要这些写
{@link ChannelPipeline} pipeline = {@link Channels#pipeline() Channels.pipeline()};
pipeline.addLast("decoder", new MyProtocolDecoder());
pipeline.addLast("encoder", new MyProtocolEncoder());
pipeline.addLast("executor", new {@link ExecutionHandler}(new {@link OrderedMemoryAwareThreadPoolExecutor}(16, 1048576, 1048576)));
pipeline.addLast("handler", new MyBusinessLogicHandler());
其中:
Protocol Decoder - 将binary转换为java对象
Protocol Encoder - 将java对象转换为binary
ExecutionHandler - applies a thread model.
Business Logic Handler - performs the actual business logic(e.g. database access)
虽然不能为channel重新设置channelPipeline,但是channelPipeline本身是thread-safe,因此你可以在任何时候为channelPipeline添加删除channelHandler
需要注意的是,下面的代码写法不能达到预期的效果
public class FirstHandler extends {@link SimpleChannelUpstreamHandler} {
*
{@code @Override}
public void messageReceived({@link ChannelHandlerContext} ctx, {@link MessageEvent} e) {
// Remove this handler from the pipeline,
ctx.getPipeline().remove(this);
// And let SecondHandler handle the current event.
ctx.getPipeline().addLast("2nd", new SecondHandler());
ctx.sendUpstream(e);
}
}
前提现在Pipeline只有最后一个FirstHandler,
上面明显是想把FirstHandler从Pipeline中移除,然后添加SecondHandler。而pipeline需要只要有一个Handler,因此如果想到到达这个效果,那么可以
先添加SecondHandler,然后在移除FirstHandler。
6.ChannelFactory
channel的工厂类,也就是用来生成channel的类,ChannelFactory根据指定的通信和网络来生成相应的channel,比如
NioServerSocketChannelFactory生成的channel是基于NIO server socket的。
当一个channel创建后,ChannelPipeline将作为参数附属给该channel。
对于channelFactory的关闭,需要做两步操作
第一,关闭所有该factory产生的channel包括子channel。通常调用ChannelGroup#close()。
第二,释放channelFactory的资源,调用releaseExternalResources()
7.ChannelGroup
channel的组集合,他包含一个或多个open的channel,closed channel会自动从group中移除,一个channel可以在一个或者多个channelGroup
如果想将一个消息广播给多个channel,可以利用group来实现
比如:
{@link ChannelGroup} recipients = new {@link DefaultChannelGroup}()
recipients.add(channelA);
recipients.add(channelB);
recipients.write(ChannelBuffers.copiedBuffer("Service will shut down for maintenance in 5 minutes.",CharsetUtil.UTF_8));
当ServerChannel和非ServerChannel同时都在channelGroup中的时候,任何io请求的操作都是先在ServerChannel中执行再在其他Channel中执行。
这个规则对关闭一个server非常适用。
8.ChannelFuture
在netty中,所有的io传输都是异步,所有那么在传送的时候需要数据+状态来确定是否全部传送成功,而这个载体就是ChannelFuture。
9.ChannelGroupFuture
针对一次ChannelGroup异步操作的结果,他和ChannelFuture一样,包括数据和状态。不同的是他由channelGroup里面channel的所有channelFuture
组成。
10.ChannelGroupFutureListener
针对ChannelGroupFuture的监听器,同样建议使用ChannelGroupFutureListener而不是await();
11.ChannelFutureListener
ChannelFuture监听器,监听channelFuture的结果。
12.ChannelFutureProgressListener
监听ChannelFuture处理过程,比如一个大文件的传送。而ChannelFutureListener只监听ChannelFuture完成未完成
13.ChannelHandlerContext
如何让handler和他的pipeLine以及pipeLine中的其他handler交换,那么就要用到ChannelHandlerContext,
ChannelHandler可以通过ChannelHandlerContext的sendXXXstream(ChannelEvent)将event传给最近的handler
可以通过ChannelHandlerContext的getPipeline来得到Pipeline,并修改他,ChannelHandlerContext还可以存放一下状态信息attments。
一个ChannelHandler实例可以有一个或者多个ChannelHandlerContext
14.ChannelPipelineFactory
产生ChannelPipe的工厂类
15.ChannelState
记载channel状态常量
分享到:
相关推荐
NettyChannel是一个基于Netty框架的测试程序,它包含了客户端(client)和服务器端(server)的实现,目的是为了深入理解Netty中的Channel概念及其工作流程。Netty是一个高性能、异步事件驱动的网络应用程序框架,...
Netty-SocketIO API接口文档是为开发者提供关于如何使用Netty-SocketIO框架进行通信的一个详细指南。Netty是一个高性能、异步事件驱动的网络应用程序框架,它简化了创建网络服务,如TCP和UDP服务器的过程。SocketIO...
Netty对Channel总结的思维导图,包括功能梳理,源码分析。
Netty4推送与Kafka消费是现代分布式系统中常见的数据通信技术。Netty是一个高性能、异步事件驱动的网络应用程序框架,常用于构建高效的服务器和客户端应用,如高并发的Web服务、游戏服务器等。而Kafka是一款强大的...
总结起来,Netty中的Java序列化是通过实现`Serializable`接口的对象转换为字节流,然后使用`ByteBuf`在网络中传输的一种方式。在实际开发中,我们可以根据性能需求选择合适的序列化策略,并结合Netty的强大功能,...
文章的对应博客https://blog.csdn.net/weixin_43333483/article/details/127716359#comments_25224363 启动后访问:http://localhost:8088/ 就可开始进行聊天
- **Channel**:在Netty中,Channel代表一个打开的连接,它可以读写数据。例如,TCP连接、UDP套接字或文件都可通过Channel进行操作。 - **EventLoop**:EventLoop是Netty的线程模型,它负责处理I/O事件并调度任务...
- Netty的基本概念:了解Netty是什么,它如何简化Java网络编程,以及它的核心组件,如Channel、EventLoop、Bootstrap等。 - 异步模型:Netty采用NIO(非阻塞I/O)模型,通过事件驱动方式实现高并发处理,提高系统...
Netty 使用了事件驱动模型,当 Channel 上发生 I/O 事件时,会触发相应的处理器进行处理。常见的事件包括连接建立、数据读取、写操作完成等。开发者可以通过实现 ChannelInboundHandler 或 ChannelOutboundHandler ...
2. **Channel**:在Netty中,Channel是连接的抽象,它代表了到另一个实体(例如,另一个网络节点)的连接。每个Channel都有自己的生命周期,可以进行读写操作,并且可以注册监听器以响应各种网络事件。 3. **...
3. `netty-channel`: 实现了基础的I/O通道接口和相关的事件处理。 4. `netty-codec`: 提供了各种编解码器,如ByteToMessageDecoder和MessageToByteEncoder。 5. `netty-codec-http`和`netty-codec-http2`: 对...
- **ChannelHandler**:处理器接口,用于实现I/O事件的处理逻辑。 - **Bootstrap**:启动器,用于配置并启动服务器或客户端。 - **ServerBootstrap**:服务器端的启动器,专门用于创建服务器Channel。 - **...
2. **Channel与Pipeline**:Netty中的Channel代表一个网络连接,负责读写数据。Pipeline(管道)则是一系列处理通道事件的处理器链,每个处理器可以对数据进行解码、编码或者执行业务逻辑。 3. **ByteBuf**:Netty...
Channel是Netty中的核心组件,代表一个网络连接,而ChannelHandler则是处理I/O事件和数据传输的处理器。 书中会详细讲解Netty的管道(Pipeline)机制,这是Netty处理网络请求的独特方式。管道由一系列的...
5. **装饰者模式(Decorator Pattern)**:Netty的ChannelHandlerContext可以看作是对原始Channel接口的装饰,增加了事件处理和管道管理的功能。 6. **状态机模式(State Pattern)**:Netty中的ChannelState可以视...
Netty基于NIO(非阻塞I/O)模型,利用了Java的Selector和Channel概念,可以高效地处理大量并发连接。它的核心组件包括Bootstrap(引导类)、ServerBootstrap(服务器引导类)、Channel(通道)、...
Netty的Channel和Pipeline是两个核心组件。Channel是网络连接的抽象,它可以是TCP、UDP或者任何其他类型的I/O连接。Pipeline则是一个处理链,每个连接都有一个自己的Pipeline,其中包含多个处理器(ChannelHandler)...
Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。这个教程将引导我们入门 Netty 编码,让我们深入理解其核心概念和实际应用。 首先,Netty 的核心是其设计...
2. **Netty架构**:Netty采用了反应器模式,包含Bootstrap(引导类)、ServerBootstrap(服务器引导类)、Channel(通道)、EventLoop(事件循环)、Pipeline(处理链)等组件,构建了高效的事件驱动模型。...