一、引言
开始学习Netty源码可以从它的启动过程入手。Netty客户端的启动需要构造一个io.netty.bootstrap.Bootstrap类,并可以通过它设置一系列参数。
我们从下面这个代码入手:
客户端的启动可以分为以下几个步骤:
1、构造Bootstrap类,这个类专门用来引导客户端
2、绑定一个EventLoopGroup作为处理连接的线程池,这的NioEventLoopGroup基于异步IO实现。
3、指定Channel通道的类型,这里指定了NioSocketChannel
4、指定连接参数(可选)
5、添加进站处理器和出站处理器用于处理客户端接收到的信息和发送的信息,这里添加了一个HTTP请求解码器和HTTP响应编码器。
6、连接指定的IP和端口。
二、Channel初始化
Netty框架实现了自己的Channel,作为Socket的抽象,每当Netty建立了一个Socket连接后都会随之建立对应的Channel。Netty自己实现的Channel实际上是对JDK中的NIO做了一层封装。
NioSocketChannel继承关系图如下:
[图片上传失败...(image-7913f1-1573573255038)]
除了NioSocketChannel,Netty还提供了其它SocketChannel接口实现类:
NioServerSocketChannel:用于异步IO的服务端TCP连接
NioDatagramChannel:用于异步IO的UDP连接
NioSctpChannel:SCTP协议的异步IO连接
NioSctpServerChannel:SCTP协议的服务端异步IO连接
OioSocketChannel:阻塞IO实现的客户端连接
OioServerSocketChannel:阻塞IO实现的服务端连接
OioDatagramSocketChannel:阻塞IO实现的UDP的服务端连接
OioSctpChannel:阻塞IO的SCTP连接
OioSctpServerChannel:阻塞IO的SCTP服务端连接
NioSocketChannel类提供了4种public构造方法:
[图片上传失败...(image-5d2bc7-1573573255038)]
三、EventLoopGroup的初始化
在Netty的线程模型中,EventLoop将由一个永远不会改变的Thread驱动,同时任务可以直接提交给EventLoop实现,已达到立刻执行或者调度执行的目的,EventLoop接口只提供了一个方法:
public interface EventLoop extends OrderedEventExecutor, EventLoopGroup {
@Override EventLoopGroup parent();
}
parent方法用于返回这个EventLoop所属的EventLoopGroup。
EventLoopGroup是一个ScheduledExecutorService线程池接口实现类,可以把它当成是一个多个线程组成线程池。
四、Bootstrap的引导
1、调用group方法绑定一个EventLoopGroup
2、指定Channel的实现类
3、指定连接参数
4、指定ChannelHandler
可以调用handler方法指定ChannelHandler用于指定一个ChannelHandler处理请求,一般为ChannelInitializer
继承 ChannelInitializer 复写 initChannel 获取 ChannelPipeline addLast 编解码 以及客户端逻辑 NettyClientHandler 继承SimpleChannelInboundHandler channelRead0 接收消息 channelActive channelInactive 连接状态 userEventTriggered 处理心跳
发送消息 channel.writeAndFlush(“。。。。。”);
5、调用Bootstrap的connect方法(有多个重载的方法)可以向指定的IP和端口发起TCP连接:
Netty中,提供IdleStateHandler 类,可以实现对三种心跳的检测,分别是readerIdleTime、writerIdleTime和allIdleTime。
三个的参数解释如下:
1)readerIdleTime:为读超时时间(即测试端一定时间内未接受到被测试端消息);
2)writerIdleTime:为写超时时间(即测试端一定时间内向被测试端发送消息)
3)allIdleTime:所有类型的超时时间;
6、心跳处理
所以在channelPipeline中加入IdleStateHandler,我们在handler中提示的是5秒读,所以我们服务端的配置的是:
ph.addLast(new IdleStateHandler(5, 0, 0, TimeUnit.SECONDS));1
因为服务端必须5秒接受一次心跳请求, 那么客户端的配置:
ph.addLast( new IdleStateHandler(0, 4, 0, TimeUnit.SECONDS));1
userEventTriggered是Netty 处理心跳超时事件,在IdleStateHandler设置超时时间,如果达到了,就会直接调用该方法。如果没有超时则不调用。我们重写该方法的话,就可以自行进行相关的业务逻辑处理了。
7、断开连接
channelFuture.channel().close();
group.shutdownGracefully();