程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长


+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

【Netty学习总结】三. 核心组件

发布于2021-04-09 07:08     阅读(432)     评论(0)     点赞(3)     收藏(2)


1. Channel

与NIO中的SocketChannel类似,Netty中的Channel也用于处理基本的I/O操作(连接,读写,绑定端口),但在Netty中对Channel进行了重新实现,主要实现类有:NioSocketChannel,NioServerSocketChannel,NioDatagramChannel

通过channel类的API,可以获取网络的连接通道状态,配置参数等

2. EventLoop和EventLoopGroup

  • EventLoop是Netty的核心抽象,用于处理连接的生命周期中发生的事件
  • 一个EventLoopGroup包含多个EventLoop,可以将EventLoop看作线程池的某一个线程
  • 每个EventLoop有自己的Selector,因此可能会有多个Channel被注册到一个EventLoop上
  • 当Channel发生读写事件时,EventLoop可以进行相应地处理

EventLoop可通过group()方法获取其所属的EventLoopGroup

任务队列:

  • EventLoop中有一任务队列(和定时任务队列),队列中的任务会被另一线程异步执行,可通过executeschedule方法向队列中提交任务或定时任务

3. ChannelFuture与异步模型

  • Netty中所有I/O操作都是异步的,在执行I/O操作后会立即返回一个ChannelFuture
  • 可以为ChannelFuture设置一个监听器,当事件执行完毕后主动回调通知监听者
ChannelFuture cf = bootstrap.connect("127.0.0.1",6666);
cf.addListener(new ChannelFutureListener(){
		@Override
		public void operationComplete(ChannelFuture channelFuture) throws Exception{
			if(channelFuture.isSuccess){
				sout("success!");
			}else{
				channelFuture.cause().printStackTrace();
			}
		}
}
  • 也可以使用sync()方法等待直到异步操作完成

4. ChannelHandler和ChannelPipeline

ChannelHandler和ChannelPipeline是Netty中最核心的组件,当Channel发生I/O事件需要被处理时,ChannelPipeline可以看作是对该事件进行处理的流水线,而ChannelHandler可以看作是流水线上的一道道工序。当各个工序都完成后,该事件也就被成功处理。

因此,当需要处理各种网络事件时,只需实现Channel的Handler,规定业务处理流程,而无需关心网络编程的细节,从而大大简化开发。

根据数据的流入流出方向,可以将ChannelHandler分为入站Handler和出站Handler:

  • 当进行入站事件处理时(如数据读取),ChannelHandler的执行顺序是从头执行到尾。通过继承ChannelInboundHandlerAdapter自定义入站Handler。
  • 当进行出站事件处理时(如数据发送),ChannelHandler的执行顺序是从尾执行到头。通过继承ChannelOutboundHandlerAdapter自定义入站Handler。
常用方法(当有对应事件发生时,就会调用相关方法):
  • ChannelUnRegistered(),ChannelRegistered()
  • ChannelActive(),ChannelInActive()
  • channelRead(),channelReadComplete()
  • handlerAdded(),handlerRemoved()
  • exceptionCaught()

使用示例:

public class NettyServerHandler extends ChannelInboundHandlerAdapter {

    /**
     * 读取数据方法
     * @param ctx 上下文对象,含有pipeline, channel, 地址
     * @param msg 客户端发送的数据
     * @throws Exception
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //将msg转为ByteBuf
        ByteBuf byteBuf = (ByteBuf) msg;
        System.out.println("客户端发送消息:" + byteBuf.toString(CharsetUtil.UTF_8));
    }

    /**
     * 读取事件完毕
     */
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        //将数据写入到缓冲并刷新,且对数据进行编码
        ctx.writeAndFlush(Unpooled.copiedBuffer("hello, client~", CharsetUtil.UTF_8));
    }

    /**
     * 处理异常,一般需要关闭通道
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }
}
注意事项
  1. 对于每一个Channel,都会为其重新生成ChannelPipeline和一组ChannelHandler,因此ChannelPipeline和ChannelHandler都是每个Channel私有的,不会发生线程安全问题
  2. ChannelInboundHandler和ChannelOutboundHandler是独立运行的,不会互相干扰,在所有ChannelInboundHandler执行完毕后才会去执行ChannelOutboundHandler。因此在向ChannelPipeline添加ChannelHandler时不用特意区分两者的顺序。

5. ChannelHandlerContext

ChannelHandlerContext可以看作是ChannelPipeline中的上下文信息,其绑定了Pipeline和Channel信息,且负责各ChannelHandler之间的交互

常用方法:

  • writeAndFlush():通过该实例写入并冲刷消息并传递给下一个Handler进行处理(如果是Channel.wirte()则是从Pipeline中的第一Handler开始处理)
  • close():关闭该Channel

原文链接:https://blog.csdn.net/wanger61/article/details/115487160




所属网站分类: 技术文章 > 博客

作者:大哥你来啦

链接:http://www.qianduanheidong.com/blog/article/58509/c6eb59877e0ad97bf50d/

来源:前端黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

3 0
收藏该文
已收藏

评论内容:(最多支持255个字符)