netty客户端异步得到返回值(netty服务端主动发送信息)
netty客户端异步得到返回值(netty服务端主动发送信息),新营销网红网本栏目通过数据整理汇集了netty客户端异步得到返回值(netty服务端主动发送信息)相关信息,下面一起看看。
简介我们知道数据传输方式有两种,分别是字符流和字节流。字符流是指要传输的对象是一个字符串,格式已经设置好了。发送方和接收方只需要按照特定的格式读取即可,而字节流是指数据以原始的二进制字节传输。
今天,我们将介绍netty中基于流的数据传输。
熟悉带包字节的TCP/IP协议的同学应该知道,在TCP/IP中,由于底层协议支持的数据包最大,所以对于大数据传输,需要对数据进行拆分和打包,发送这些拆分和组装后的数据包,在接收端对这些数据包进行合并。每个包中有一个固定的结构,所以接收方可以清楚地知道应该组合多少个包作为最终结果。
那么对于netty来说,信道中传输的是ByteBuf,实际上最底层是字节数组。对于这个字节数组,接收方并不确切知道应该组合多少字节来合成原始消息,需要在接收方组合接收到的字节来生成最终数据。
那么netty中的字节数据流应该如何组合呢?接下来我们来看两个组合。
手动组合这种组合的基本思想是构造一个目标大小的ByteBuf,然后通过调用ByteBuf的writeBytes将接收到的字节写入ByteBuf。,从ByteBuf中读取相应的数据。
例如,我们想从服务器向客户端发送一个int数。,int是32位,那么一个字节就是8位,所以一个int需要4个字节。
在服务器端,您可以构建一个包含四个元素的byte数组。将4个元素的字节发送给客户端,那么客户端应该怎么做?
我们需要建立一个clientHander,这个client hander应该继承ChannelInboundhandlerAdapter,并在它的handler添加到ChannelPipeline时初始化一个包含4 byte的byteBuf。
当添加一个处理程序时,将会触发一个handlerAdded事件,所以我们可以这样写
private ByteBuf buf添加了@ override公共void处理程序(channelhandler上下文CTX){//创建一个4字节的缓冲区buf=ctx.alloc()。缓冲区(4);}在上面的例子中,我们从ctx中分配了一个4字节的缓冲区,并将其赋给handler中的私有变量buf。
当处理程序被执行并从ChannelPipeline中删除时,将触发handlerRemoved事件。在这种情况下,我们可以清理分配的Bytebuf。,我们可以称其为释放,如下图所示
public void handler removed(ChannelHandlerContext CTX){ buf . release();//release buf buf=null;}那么最关键的一步就是从通道中读取字节,放入4字节的byteBuf中。在上一篇文章中,我们提到消息读取的逻辑可以在channelRead中处理。
public void channel read(ChannelHandlerContext CTX,Object msg){ byte buf m=(byte buf)msg;buf . write bytes(m);//写一个bytem . release();If (buf.readableBytes()=4) {//已经收集了四个字节,四个字节的组合称为一个intlongresult=buf . readunsignedint();CTX . close();}}每次触发channelRead,都会通过调用writeBytes将one byte read的字节写入buf。当buf的可读取字节数大于等于4时,表示4个字节已经被完全读取,可以进行操作。
这里我们把四个字节组合成一个unsignedInt,用readUnsignedInt从buf中读出组合,称为Int数。
虽然上面的例子可以解决4字节的字节问题,如果数据结构更负责任,那么上面的方法就不充分了,需要考虑太多的数据组合问题。接下来,我们来看另一种方式。
Byte的转换类Netty提供了ByteToMessageDecoder的转换类,可以很方便的将Byte转换成其他类型。
我们只需要重新解码就可以实现ByteBuf的转换
公共类平方解码器扩展ByteToMessageDecoder { @ override public void decode(ChannelHandlerContext CTX,ByteBuf in,List Object out)抛出异常{出去。添加(在。读取字节(in。可读字节()));}}上面的例子将字节从投入转换到输出中,,你还可以在上面的中进行格式转换,如下所示
公共类时间解码器扩展
nds ByteToMessageDecoder {@Overrideprotected void decode(ChannelHandlerContext ctx, ByteBuf in, List Object out) {if (in.readableBytes() 4) {return;}out.add(in.readBytes(4));}}
上面的例子会先判断in中是否有4个byte,如果有就将其读出来放到out中去。那么有同学会问了,输入不是一个byte一个byte来的吗?为什么这里可以一次读取到4个byte?这是因为ByteToMessageDecoder内置了一个缓存装置,所以这里的in实际上是一个缓存 。
ReplayingDecoder
netty还提供了一个更简单的转换ReplayingDecoder,如果使用ReplayingDecoder重新上面的逻辑就是这样的
public class TimeDecoder extends ReplayingDecoder Void {@Overrideprotected void decode(ChannelHandlerContext ctx, ByteBuf in, List Object out) {out.add(in.readBytes(4));}}
只需要一行代码即可。
事实上ReplayingDecoder 是ByteToMessageDecoder 的子类,是在ByteToMessageDecoder上丰富了一些功能的结果。
他们两的区别在于ByteToMessageDecoder 还需要通过调用readableBytes来判断是否有足够的可以读byte,而使用ReplayingDecoder直接读取即可,它假设的是所有的bytes都已经接受成功了。
比如下面使用ByteToMessageDecoder的代码
public class IntegerHeaderFrameDecoder extends ByteToMessageDecoder {@Overrideprotected void decode(ChannelHandlerContext ctx,ByteBuf buf, List Object out) throws Exception {if (buf.readableBytes() 4) {return;}buf.markReaderIndex();int length = buf.readInt();if (buf.readableBytes() length) {buf.resetReaderIndex();return;}out.add(buf.readBytes(length));}}
上例假设在byte的头部是一个int大小的数组,代表着byte数组的长度,需要先读取int值,然后再根据int值来读取对应的byte数据。
和下面的代码是等价的
public class IntegerHeaderFrameDecoderextends ReplayingDecoder Void {protected void decode(ChannelHandlerContext ctx,ByteBuf buf, List Object out) throws Exception {out.add(buf.readBytes(buf.readInt()));}}
上面代码少了判断的步骤。
那么这是怎么实现的呢?
事实上ReplayingDecoder 会传递一个会抛出 Error的 ByteBuf , 当 ByteBuf 读取的byte个数不满足要求的时候,会抛出异常,当ReplayingDecoder 捕获到这个异常之后,会重置buffer的readerIndex到最初的状态,然后等待后续的数据进来,然后调用decode 。
所以,ReplayingDecoder的效率会比较低,为了解决这个问题,netty提供了checkpoint() 。这是一个保存点,当报错的时候,可以不会退到最初的状态,而是回退到checkpoint() 调用时候保存的状态,从而可以减少不必要的浪费。
本文介绍了在netty中进行stream操作和变换的几种方式,希望大家能够喜欢。
相关文章
豪杰超级解霸(还记得豪杰超级解霸吗?)
龚自珍的资料(清代诗人龚自珍一生功绩简介)
象牙塔是什么意思(“象牙塔”里怎么了?)
水色风信子(水培风信子容易养)
婧字怎么读
虞姬是哪里人(古代著名美人虞姬到底是哪里人?)
公办三本院校(我们还有哪些“三本”?)
电子酒柜(酒柜最全选购指南)
德州景点(德州市景区景点62个)
玉兰油官方网(OLAY发布高端臻粹系列)
驱鬼咒语(道教辟邪的神咒)
奥运五环代表什么(奥运会五环代表着什么?)
更多netty客户端异步得到返回值(netty服务端主动发送信息)相关信息请关注本文章,本文仅仅做为展示!