- 浏览: 981593 次
文章分类
- 全部博客 (428)
- Hadoop (2)
- HBase (1)
- ELK (1)
- ActiveMQ (13)
- Kafka (5)
- Redis (14)
- Dubbo (1)
- Memcached (5)
- Netty (56)
- Mina (34)
- NIO (51)
- JUC (53)
- Spring (13)
- Mybatis (17)
- MySQL (21)
- JDBC (12)
- C3P0 (5)
- Tomcat (13)
- SLF4J-log4j (9)
- P6Spy (4)
- Quartz (12)
- Zabbix (7)
- JAVA (9)
- Linux (15)
- HTML (9)
- Lucene (0)
- JS (2)
- WebService (1)
- Maven (4)
- Oracle&MSSQL (14)
- iText (11)
- Development Tools (8)
- UTILS (4)
- LIFE (8)
最新评论
-
Donald_Draper:
Donald_Draper 写道刘落落cici 写道能给我发一 ...
DatagramChannelImpl 解析三(多播) -
Donald_Draper:
刘落落cici 写道能给我发一份这个类的源码吗Datagram ...
DatagramChannelImpl 解析三(多播) -
lyfyouyun:
请问楼主,执行消息发送的时候,报错:Transport sch ...
ActiveMQ连接工厂、连接详解 -
ezlhq:
关于 PollArrayWrapper 状态含义猜测:参考 S ...
WindowsSelectorImpl解析一(FdMap,PollArrayWrapper) -
flyfeifei66:
打算使用xmemcache作为memcache的客户端,由于x ...
Memcached分布式客户端(Xmemcached)
netty 消息解码器-ByteToMessageDecoder:http://donald-draper.iteye.com/blog/2388088
netty 默认Channel管道线-Inbound和Outbound事件处理:http://donald-draper.iteye.com/blog/2389148
netty 通道处理器上下文定义:http://donald-draper.iteye.com/blog/2389214
netty 通道处理器上下文:http://donald-draper.iteye.com/blog/2389299
引言:
在前面的文章中,我们看了通道处理器,Channel管道线,和通道上下文,梳理了他们之间的关系,那么通道处理器如何添加通道的管道中呢?这个不得不提通道初始化器ChannelInitializer。
在netty的相关demo实例中,有这么一段:
今天我们关注的是通道处理器的初始化:
上面一段代码,有一个通道处理器初始化类ChannelInitializer,
这个类就是今天我们要看的:
总结:
通道初始化器ChannelInitializer实际上为Inbound通道处理器,当通道注册到事件循环中后,添加通道初始化器到通道,触发handlerAdded事件,然后将初始化器的上下文放入通道初始化器的上下文Map中,如果放入成功且先前不存在,initChannel(C ch),初始化通道,其中C为当前通道,我们可以获取C的管道,添加通道处理器到管道,这就是通道初始化器的作用。
添加完后,从通道的管道中移除初始化器上下文,并从通道初始化器的上下文Map中移除通道初始化器上下文。
netty 默认Channel管道线-Inbound和Outbound事件处理:http://donald-draper.iteye.com/blog/2389148
netty 通道处理器上下文定义:http://donald-draper.iteye.com/blog/2389214
netty 通道处理器上下文:http://donald-draper.iteye.com/blog/2389299
引言:
在前面的文章中,我们看了通道处理器,Channel管道线,和通道上下文,梳理了他们之间的关系,那么通道处理器如何添加通道的管道中呢?这个不得不提通道初始化器ChannelInitializer。
在netty的相关demo实例中,有这么一段:
EventLoopGroup workerGroup = new NioEventLoopGroup(); try { //Bootstrap,用于配置客户端,一般为Socket通道 Bootstrap bootstrap = new Bootstrap(); bootstrap.group(workerGroup) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { //添加安全套接字处理器和通道处理器到 ChannelPipeline pipeline = ch.pipeline(); if (sslCtx != null) { pipeline.addLast(sslCtx.newHandler(ch.alloc(), ip, port)); } pipeline.addLast(new LoggingHandler(LogLevel.INFO)); pipeline.addLast(new EchoClientHandler()); } }); InetSocketAddress inetSocketAddress = new InetSocketAddress(ip,port); //连接socket地址 ChannelFuture f = bootstrap.connect(inetSocketAddress).sync(); log.info("=========Client is start========="); //等待,直到连接关闭 f.channel().closeFuture().sync(); } finally { workerGroup.shutdownGracefully(); }
今天我们关注的是通道处理器的初始化:
.handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { //添加安全套接字处理器和通道处理器到 ChannelPipeline pipeline = ch.pipeline(); if (sslCtx != null) { pipeline.addLast(sslCtx.newHandler(ch.alloc(), ip, port)); } pipeline.addLast(new LoggingHandler(LogLevel.INFO)); pipeline.addLast(new EchoClientHandler()); } });
上面一段代码,有一个通道处理器初始化类ChannelInitializer,
这个类就是今天我们要看的:
package io.netty.channel; import io.netty.bootstrap.Bootstrap; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelHandler.Sharable; import io.netty.util.internal.PlatformDependent; import io.netty.util.internal.logging.InternalLogger; import io.netty.util.internal.logging.InternalLoggerFactory; import java.util.concurrent.ConcurrentMap; /** * A special {@link ChannelInboundHandler} which offers an easy way to initialize a {@link Channel} once it was * registered to its {@link EventLoop}. *ChannelInitializer是一个特殊的inboun通道处理器,一旦通道注册到事件循环中时,提供一个便捷的初始化通道的方式。 * Implementations are most often used in the context of {@link Bootstrap#handler(ChannelHandler)} , * {@link ServerBootstrap#handler(ChannelHandler)} and {@link ServerBootstrap#childHandler(ChannelHandler)} to * setup the {@link ChannelPipeline} of a {@link Channel}. *具体的实现一般在Bootstrap#handler(ChannelHandler) ,ServerBootstrap#handler(ChannelHandler)和 ServerBootstrap#childHandler(ChannelHandler)中,设置Channel的管道。 * <pre> * * public class MyChannelInitializer extends {@link ChannelInitializer} { * public void initChannel({@link Channel} channel) { * channel.pipeline().addLast("myHandler", new MyHandler()); * } * } * * {@link ServerBootstrap} bootstrap = ...; * ... * bootstrap.childHandler(new MyChannelInitializer()); * ... * </pre> * Be aware that this class is marked as {@link Sharable} and so the implementation must be safe to be re-used. *注意此类为共享类型,具体的实现必须是线程安全的。 * @param <C> A sub-type of {@link Channel} 参数类型C为通道的子类 */ @Sharable public abstract class ChannelInitializer<C extends Channel> extends ChannelInboundHandlerAdapter { private static final InternalLogger logger = InternalLoggerFactory.getInstance(ChannelInitializer.class); // We use a ConcurrentMap as a ChannelInitializer is usually shared between all Channels in a Bootstrap / // ServerBootstrap. This way we can reduce the memory usage compared to use Attributes. //由于通道初始器经常在Bootstrap /ServerBootstrap的所有通道中共享,所以我们用一个ConcurrentMap作为初始化器。 //这种方式,相对于使用属性方式,减少了内存的使用。 private final ConcurrentMap<ChannelHandlerContext, Boolean> initMap = PlatformDependent.newConcurrentHashMap(); //注册通道处理器动事件循环 @Override @SuppressWarnings("unchecked") public final void channelRegistered(ChannelHandlerContext ctx) throws Exception { // Normally this method will never be called as handlerAdded(...) should call initChannel(...) and remove // the handler. //正常情况下这个方法不为被调用,因为handlerAdded可以用于初始化通道 if (initChannel(ctx)) { // we called initChannel(...) so we need to call now pipeline.fireChannelRegistered() to ensure we not // miss an event. //调用上下文关联通道的fireChannelRegistered,确保不会调试事件 ctx.pipeline().fireChannelRegistered(); } else { // Called initChannel(...) before which is the expected behavior, so just forward the event. //转发事件 ctx.fireChannelRegistered(); } } /** * {@inheritDoc} If override this method ensure you call super! 如果重写,必须保证能够调用super */ @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { //当通道注册到事件循环中 if (ctx.channel().isRegistered()) { // This should always be true with our current DefaultChannelPipeline implementation. // The good thing about calling initChannel(...) in handlerAdded(...) is that there will be no ordering // surprises if a ChannelInitializer will add another ChannelInitializer. This is as all handlers // will be added in the expected order //在当前默认Channel管道下的实现下,总是返回true。在handlerAdded方法中调用initChannel方法好处是,如果一个初始化器 //添加到另外一个初始化器,不会从排序。所有的通道处理器将会以期望的顺序添加Channel管道中 initChannel(ctx); } } //初始化通道处理器上下文 @SuppressWarnings("unchecked") private boolean initChannel(ChannelHandlerContext ctx) throws Exception { //将上下文放入通道初始化器的上下文Map中 if (initMap.putIfAbsent(ctx, Boolean.TRUE) == null) { // Guard against re-entrance. try { //添加成功,则调用initChannel(C ch),初始化通道 initChannel((C) ctx.channel()); } catch (Throwable cause) { // Explicitly call exceptionCaught(...) as we removed the handler before calling initChannel(...). // We do so to prevent multiple calls to initChannel(...). //异常发生则抛出log异常,并关闭上下文 exceptionCaught(ctx, cause); } finally { //最后从通道初始化器的上下文Map移除当前上下文 remove(ctx); } return true; } return false; } /** * This method will be called once the {@link Channel} was registered. After the method returns this instance * will be removed from the {@link ChannelPipeline} of the {@link Channel}. *一旦通道注册,此方法将会被调用。方法将会调用完毕,此处理器实例将会从通道的管道中移除 * @param ch the {@link Channel} which was registered. * @throws Exception is thrown if an error occurs. In that case it will be handled by * {@link #exceptionCaught(ChannelHandlerContext, Throwable)} which will by default close * the {@link Channel}. */ protected abstract void initChannel(C ch) throws Exception; /** * Handle the {@link Throwable} by logging and closing the {@link Channel}. Sub-classes may override this. 处理异常,并关闭上下文 */ @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { logger.warn("Failed to initialize a channel. Closing: " + ctx.channel(), cause); ctx.close(); } //移除通道处理器上下文 private void remove(ChannelHandlerContext ctx) { try { //从当前通道的管道中移除上下文 ChannelPipeline pipeline = ctx.pipeline(); if (pipeline.context(this) != null) { pipeline.remove(this); } } finally { //从通道初始化器上下文Map移除上下文 initMap.remove(ctx); } } }
总结:
通道初始化器ChannelInitializer实际上为Inbound通道处理器,当通道注册到事件循环中后,添加通道初始化器到通道,触发handlerAdded事件,然后将初始化器的上下文放入通道初始化器的上下文Map中,如果放入成功且先前不存在,initChannel(C ch),初始化通道,其中C为当前通道,我们可以获取C的管道,添加通道处理器到管道,这就是通道初始化器的作用。
添加完后,从通道的管道中移除初始化器上下文,并从通道初始化器的上下文Map中移除通道初始化器上下文。
发表评论
-
netty NioSocketChannel解析
2017-09-29 12:50 1321netty 抽象BootStrap定义:http://dona ... -
netty Pooled字节buf分配器
2017-09-28 13:00 2057netty 字节buf定义:http://donald-dra ... -
netty Unpooled字节buf分配器
2017-09-26 22:01 2447netty 字节buf定义:http://donald-dra ... -
netty 抽象字节buf分配器
2017-09-26 08:43 1317netty 字节buf定义:http:// ... -
netty 复合buf概念
2017-09-25 22:31 1310netty 字节buf定义:http://donald-dra ... -
netty 抽象字节buf引用计数器
2017-09-22 12:48 1596netty 字节buf定义:http://donald-dra ... -
netty 抽象字节buf解析
2017-09-22 09:00 1844netty 通道接口定义:http://donald-drap ... -
netty 资源泄漏探测器
2017-09-21 09:37 1398netty 通道接口定义:http://donald-drap ... -
netty 字节buf定义
2017-09-20 08:31 2834netty 通道接口定义:http://donald-drap ... -
netty 默认通道配置后续
2017-09-18 08:36 2179netty 通道接口定义:http://donald-drap ... -
netty 默认通道配置初始化
2017-09-17 22:51 2037netty 通道接口定义:http://donald-drap ... -
netty 通道配置接口定义
2017-09-17 14:51 1079netty 通道接口定义:http://donald-drap ... -
netty NioServerSocketChannel解析
2017-09-16 13:01 1877netty ServerBootStrap解析:http:// ... -
netty 抽象nio消息通道
2017-09-15 15:30 1219netty 通道接口定义:http:/ ... -
netty 抽象nio字节通道
2017-09-14 22:39 1203netty 通道接口定义:http:/ ... -
netty 抽象nio通道解析
2017-09-14 17:23 958netty 通道接口定义:http://donald-drap ... -
netty 抽象通道后续
2017-09-13 22:40 1311netty Inboudn/Outbound通道Inv ... -
netty 通道Outbound缓冲区
2017-09-13 14:31 2191netty 通道接口定义:http:/ ... -
netty 抽象Unsafe定义
2017-09-12 21:24 1077netty 通道接口定义:http:/ ... -
netty 抽象通道初始化
2017-09-11 12:56 1857netty 管道线定义-ChannelPipeline:htt ...
相关推荐
7. **频道初始化器(ChannelInitializer)**:在 Netty 中,我们使用 ChannelInitializer 配置新建立的通道,添加必要的处理器到处理器管道,以便处理进来的连接和消息。 8. **线程模型**:理解 Netty 的 Boss-...
2. **通道初始化(ChannelInitializer)**:在初始化器中,我们添加所需的处理器到通道管道,如解码器、编码器和业务处理器。 3. **连接处理**:当客户端连接到服务器时,会触发ChannelActive事件,我们可以在这个...
- 使用ChannelInitializer为通道初始化处理器。 - 实现具体的业务逻辑处理器SimpleServerHandler。 - 将处理器添加到Pipeline中。 - 启动并绑定监听端口。 ***ty客户端编程细节 - 创建客户端启动组件Bootstrap...
在Server端,我们可以使用`ServerBootstrap.bind()`方法绑定监听端口,并设置`ChannelInitializer`来初始化每个新建立的连接,这里可以注册自定义的`ChannelInboundHandlerAdapter`来处理接收到的数据。而在Client端...
Netty的`Bootstrap`类是用来初始化和配置服务器的启动参数,如绑定的IP地址和端口号、事件循环组、处理器链等。例如,我们可以通过以下代码创建一个简单的Netty服务器: ```java EventLoopGroup bossGroup = new ...
2. 添加自定义的 ChannelInitializer,用于在 Channel 初始化时设置 ChannelPipeline 中的 Handler。 3. 绑定客户端的 Handler,通常包含编码(将业务对象转换为 ByteBuf)和解码(将 ByteBuf 转换回业务对象)逻辑...
`TimeServer`类就是这样一个启动点,它会初始化Netty服务器并监听指定的端口。在`TimeServer`的`main`函数中,会设置一个`ServerBootstrap`,配置一个`childHandler`,该处理器会处理连接到服务器的所有新通道。`...
7. **ChannelInitializer**:用于初始化新创建的Channel,设置其Pipeline中的处理器。 Netty的事件驱动模型是它高效性能的关键。当接收到网络事件时,如连接建立、数据到达、连接关闭等,Netty会将这些事件封装成...
Netty的核心组件包括Bootstrap(启动器)、Channel(通道)、Handler(处理器)和EventLoop(事件循环),它们协同工作以实现高效的数据传输。 创建Web Service服务端,首先我们需要配置一个ServerBootstrap,它是...
1. **通道初始化**: 在 Netty 中,客户端首先创建一个 `Bootstrap` 实例,用于配置客户端连接。通过设置 `ChannelInitializer`,我们可以为每个新创建的 `Channel` 添加处理器(`ChannelHandler`)链,处理进来的...
2. **指定通道处理器**: 服务端需要定义一个ChannelInitializer,这个初始化器会在建立连接时被调用,用于配置新创建的Channel。在这里,我们可能会注册一个服务端接收消息的处理器。 3. **绑定端口并启动**: 通过...
- `ChannelInitializer`:用于初始化Channel时注册各种处理器。 - `ChannelInboundHandlerAdapter` 和 `ChannelOutboundHandlerAdapter`:为入站和出站事件提供默认的空实现。 ### 总结 通过对Netty源码依赖包的...
在服务器端,首先需要创建一个`ServerBootstrap`实例,然后配置通道初始化器`ChannelInitializer`,用于在通道激活时设置处理器pipeline。在这个pipeline中,我们通常会添加`EchoServerHandler`,负责接收并回显...
3. 发送请求到服务器:在`channelActive`方法中可以发送初始化请求,或者在其他地方根据业务逻辑发送请求。 4. 错误处理:在`exceptionCaught`方法中捕获并处理异常。 最后,别忘了在不使用时关闭连接和资源,避免...
Bootstrap是Netty中的一个启动类,用于配置并初始化Netty服务。它有两个主要实现:`Bootstrap`和`ServerBootstrap`,分别用于客户端和服务端的初始化。 #### 类AbstractBootstrap 这是一个抽象基类,为`Bootstrap`...
.handler(new ChannelInitializer() { // 设置初始化处理器 @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new MyServerHandler()); // 添加自定义的...
接着,定义 `ChannelInitializer`,在这个初始化器中,我们设置服务器的通道处理链,添加自定义的处理器,如 `WebSocketServerHandler`。最后,启动服务器并绑定指定的端口。 2. **WebSocketServerHandler**(对应...
1. **初始化 Bootstrap**:首先,我们需要创建一个 `Bootstrap` 实例,这是 Netty 中启动服务器的基本配置类。通过调用 `new Bootstrap()` 来创建。 2. **配置 Channel**:接着,我们指定通道类型为 `Nio...
在Netty中,服务器的初始化通常涉及以下几个步骤: 1. 创建一个`EventLoopGroup`,这是Netty中的工作线程组,负责处理I/O事件。 2. 定义`Bootstrap`实例,它是服务器端的启动配置类。 3. 配置`Bootstrap`,包括绑定...
然后,我们在通道初始化器中添加了一个LengthFieldBasedFrameDecoder来处理粘包和拆包问题,并添加了自己的业务处理器MyBusinessHandler来处理解码后的数据。 总的来说,Netty通过提供一系列的工具和组件,使得在...