首页 > 其他分享 >【Netty】关于netty的入门问题

【Netty】关于netty的入门问题

时间:2023-08-23 12:55:04浏览次数:34  
标签:Netty 入门 netty ChannelHandlerContext ctx channelRead 数据 方法 Channel

1、netty 是什么

2、关于netty 中的 pipeline.addLast(xxxxHandler)

这个 xxxHandler 是 ChannelHandlerAdapter 的实现类,
ChannelHandlerAdapter 有好些方法,也很常见,
一直有一些问题,这里加了这么多handler,它在执行的时候,是每一个都会经过的吗?发送的时候会经过吗?响应的时候会经过吗?是不是每次的发送和响应,这些handler都会经过呢?这些Handler 方法,实现的方法,不尽相同,虽然大多数都是重写 channelRead 或 channelRead0 方法,为什么这样子呢,

一直疑惑中:至此,做一下笔记:

  • 这么多handler,每一个都会经过吗?
    会经过的,但,如果对应的方法没有重写的话,其实也和没有调用是差不太多。只有重写过的方法,可能才会有业务意义。

  • 发送的时候会经过吗?
    在这里,发送包的时候,不会经过,因为 ChannelHandlerAdapter 都是在处理消息响应的时候,
    如果要处理发送时候添加业务,比如在

    • bind(ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise):在连接远程端点之前,将 Channel 绑定到本地地址。
    • connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise):在发起连接到远程端点之前执行连接操作。
    • write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise):将要发送给远程端点的消息写入 Channel。
    • flush(ChannelHandlerContext ctx):刷新数据,确保数据被发送到远程端点。

    这几类型的操作的前后进行操作,那就需要添加另外一个 handler —— ChannelOutboundHandler 这个Handler 才能够满足冤枉。
    不过用得不多。

  • 响应的时候会经过吗?(这里说的响应,其实指的是:收到消息的时候,非发送状态,即响应状态)
    是的。如果是实现ChannelHandlerAdapter的handler, 它是对于消息响应时做的方法重写。比如

    • channelRegistered(ChannelHandlerContext ctx):当 Channel 注册到 EventLoop 后被调用。
    • channelUnregistered(ChannelHandlerContext ctx):当 Channel 从 EventLoop 取消注册后被调用。
    • channelActive(ChannelHandlerContext ctx):当 Channel 处于活动状态(已经连接到远程端点)时被调用。
    • channelInactive(ChannelHandlerContext ctx):当 Channel 处于非活动状态(已经断开与远程端点的连接)时被调用。
    • channelRead(ChannelHandlerContext ctx, Object msg):当从 Channel 读取到新的数据时被调用。(特别是这个,或者是 channelRead0)
    • channelReadComplete(ChannelHandlerContext ctx):当 Channel 中的数据读取完成时被调用。 (和这个用得多,读取响应消息,用得多)
    • exceptionCaught(ChannelHandlerContext ctx, Throwable cause):当处理过程中捕获到异常时被调用。

    所以,一般情况下,看到的 handler都是对于响应的handle, encode, decode 的除外,编解码的是属于另外一种的 handler。

  • channelRead 或 channelRead0 方法 有什么不同呢?

channelRead 和 channelRead0 都是 Netty 中用于处理接收到的消息的方法,它们之间的区别在于参数的类型。

具体来说,区别如下:
channelRead(ChannelHandlerContext ctx, Object msg):
参数 msg 的类型是 Object,即通用的消息类型。
这个方法是在 ChannelInboundHandler 接口中定义的。
在 Netty 4.x 版本中使用。


channelRead0(ChannelHandlerContext ctx, I msg):
参数 msg 的类型是泛型类型 I,即特定的消息类型。
这个方法是在 SimpleChannelInboundHandler 类中定义的。
在 Netty 5.x 版本及以后的版本中使用。

需要注意的是,在 Netty 5.x 版本之前,Netty 使用的是 channelRead 方法来处理接收到的消息。而在 Netty 5.x 版本及以后,为了提供更好的类型安全性和便利性,引入了 channelRead0 方法,并将其定义在 SimpleChannelInboundHandler 类中。

这两个方法都是被动触发的,当有数据从网络中读取到时,Netty 会自动调用相应的方法来处理这些数据。开发者可以根据实际需求选择合适的方法来处理接收到的消息。

  • channelRead 和 channelReadComplete 有什么不同

channelRead 和 channelReadComplete 是 ChannelInboundHandler 接口中的两个方法,用于处理从 Channel 读取数据的不同阶段。

channelRead(ChannelHandlerContext ctx, Object msg) 方法在从 Channel 读取到新的数据时被调用。每当有新的数据可供读取时,该方法就会被触发执行。您可以在这个方法中对接收到的数据进行解析、处理和相应的逻辑操作。

channelReadComplete(ChannelHandlerContext ctx) 方法在 Channel 中的数据读取完成时被调用。它表示当前读取操作已经完成,可以进行相应的后续处理。在这个方法中,您可以执行一些收尾工作,比如刷新数据或发起进一步操作。

通常情况下,channelRead 方法可能会被多次调用,每次读取到一部分数据。而当所有数据都被读取完毕后,channelReadComplete 方法会被调用一次,表示整个数据读取过程已经完成。

需要注意的是,在 channelRead 方法中处理数据时,可能并不一定是完整的消息。对于基于 TCP 的协议,例如 HTTP 或自定义协议,一个完整的消息可能会被分成多个 TCP 包进行传输。因此,您可能需要在接收到足够的数据后才能进行完整的处理,或者缓存已接收到的数据等待后续的组装。

总结起来,channelRead 方法用于处理从 Channel 读取到的数据,而 channelReadComplete 方法表示整个数据读取过程已经完成。

  • 和 channelReadComplete 相比,channelRead 可能是一个未完成的状态,那它有什么样的应用场景呢?

channelRead 方法的主要应用场景是在接收到数据的过程中进行实时处理和解析。由于网络传输的特性,可能无法一次性获取完整的消息,而是需要逐步接收并处理数据

以下是一些使用 channelRead 的常见场景:

数据流处理:当从 Channel 接收到数据流时,可以使用 channelRead 方法对数据进行流式处理,逐个读取和处理数据块,而不必等待所有数据完全接收。

消息解析和处理:在协议层面的通信中,可以使用 channelRead 方法将接收到的字节流逐步解析为具体的消息格式,并在解析到足够的内容后进行相应的逻辑处理。

分段数据处理:某些协议或数据格式可能将大的数据块分成多个数据段进行传输,channelRead 可以用于在每个数据段到达时进行处理,直到接收到完整的数据。

长连接处理:在长连接场景中,channelRead 方法可以用于实时处理每次接收到的数据片段,例如即时聊天、实时推送等。

需要注意的是,在使用 channelRead 进行数据处理时,可能需要进行数据缓存,以便在接收到完整的数据后进行组装和处理。

总结起来,channelRead 方法的应用场景主要是需要逐步接收和处理数据的情况,可以进行实时处理和解析

(有一些场景下,可能没有 compelete 。。。。)
在一些拆很多个小包,流式传输,长连接等场景下,可能永远都等不到 compelete, 可能等到了也很久后,或一次性要处理的东西就太多了,这种场景下, compelete 不见得是好的。

  • bootstrap.connect(ip, port) 客户端向服务端发起连接,会执行pipeline下面的 handler吗
    客户端向服务端发起连接时,这些 handler 也是会走的。
    这个时候, ChannelHandlerAdapter 中的 connect 方法,也会体现出来,通过重写这个 connect, 前后添加业务逻辑是可以的。

标签:Netty,入门,netty,ChannelHandlerContext,ctx,channelRead,数据,方法,Channel
From: https://www.cnblogs.com/aaacarrot/p/17650902.html

相关文章

  • Android入门教程之Activity(生命周期,启动...)
    Activity是一个应用组件,用户可与其提供的屏幕进行交互,以执行拨打电话、拍摄照片、发送电子邮件或查看地图等操作。每个Activity都会获得一个用于绘制其用户界面的窗口。窗口通常会充满屏幕,但也可小于屏幕并浮动在其他窗口之上。Activity1.Activity的使用我们新建的工程中带有......
  • Python基础入门学习笔记 070 GUI的终极选择:Tkinter7
    实例1:添加Tags1fromtkinterimport*23root=Tk()4text=Text(root,width=30,height=5)5text.pack()67#INSERT索引表示插入光标当前的位置8text.insert(INSERT,"IloveFishC.com!")#光标当前的位置插入9#注意,行号从1开始,列号则从0开始10text.ta......
  • Python基础入门学习笔记 067 GUI的终极选择:Tkinter4
    实例1:1fromtkinterimport*23root=Tk()#创建主窗口4e=Entry(root)#在主窗口中插入输入框5e.pack(padx=20,pady=20)67e.delete(0,END)#清空输入框8e.insert(0,"默认文本...")#设置输入框内容910mainloop() 实例2:1fromtkinterimp......
  • Python基础入门学习笔记 068 GUI的终极选择:Tkinter5
    Listbox组件如果需要提供选项给用户选择,单选可以用Radiobutton组件,多选可以用Checkbutton,如果提供的选项非常多,可以考虑使用Listbox组件。Listbox是以列表的形式显示出来,并支持滚动条操作。实例1:1fromtkinterimport*23root=Tk()#创建主窗口45theLB=Listb......
  • Python基础入门学习笔记 069 GUI的终极选择:Tkinter6
    Text组件Text(文本)组件用于显示和处理多种任务。虽然该组件的主要目的是显示多行文本,但它常常也被用于作为简单的文本编辑器和网页浏览器使用。实例1:插入内容1fromtkinterimport*23root=Tk()4text=Text(root,width=30,height=2)5text.pack()6#INSERT......
  • Python基础入门学习笔记 066 GUI的终极选择:Tkinter3
    实例1:Checkbutton组件1fromtkinterimport*23root=Tk()4#需要一个Tkinter变量,用于表示该按钮是否被选中5v=IntVar()6c=Checkbutton(root,text="测试一下",variable=v)78c.pack()9#如果被选中,那么变量v被赋值为1,否则为010#可以用个Label......
  • Python基础入门学习笔记 064 GUI的终极选择:Tkinter
    >>>importtkinter #Tkinter是python默认的GUI库,导入Tkinter模块>>> 实例1:1importtkinterastk23root=tk.Tk()#创建一个主窗口,用于容纳整个GUI程序4root.title("FishCDemo")#设置主窗口对象的标题栏56#添加一个Label组件,可以显示文本、图标或者图......
  • Python基础入门学习笔记 065 GUI的终极选择:Tkinter2
    实例1:Label组件显示文字与gif图片1#导入tkinter模块的所有内容2fromtkinterimport*34#创建主窗口5root=Tk()6#创建一个文本Label对象,文字为左对齐,离左边边框距离为107textLabel=Label(root,8text="您下载的影片含有未成年人......
  • Python基础入门学习笔记 048 魔法方法:迭代器
    迭代的意思类似于循环,每一次重复的过程被称为一次迭代的过程,而每一次迭代得到的结果会被用来作为下一次迭代的初始值。提供迭代方法的容器称为迭代器(如序列(列表、元组、字符串)、字典等)。对一个容器对象调用iter()就得到它的迭代器,调用next()迭代器就会返回下一个值。入托迭代器没......
  • Python基础入门学习笔记 049 乱入:生成器
    所谓协同程序,就是可以运行的独立函数调用,函数可以暂停或者挂起,并在需要的时候从程序离开的地方继续或者重新开始。生成器可以暂时挂起函数,并保留函数的局部变量等数据,然后在再次调用它的时候,从上次暂停的位置继续执行下去。一个函数中如果有yield语句,则被定义为生成器。实例1:......