77百科网
当前位置: 首页 生活百科

netty客户端发送数据并接收返回值(netty获取数据结束)

时间:2023-08-15 作者: 小编 阅读量: 1 栏目名: 生活百科

手动组合这种组合的方式的基本思路是构造一个目标大小的ByteBuf,然后将接收到的byte通过调用ByteBuf的writeBytes方法写入到ByteBuf中。在server端,可以建立一个byte的数组,数组中包含4个元素。这里我们将4个字节组合成一个unsignedInt,并使用readUnsignedInt方法从buf中读取出来组合称为一个int数字。这是因为ByteToMessageDecoder内置了一个缓存装置,所以这里的in实际上是一个缓存集合。

netty客户端发送数据并接收返回值?我们知道由两种数据的传输方式,分别是字符流和字节流,字符流的意思是传输的对象就是字符串,格式已经被设置好了,发送方和接收方按照特定的格式去读取就行了,而字节流是指将数据作为最原始的二进制字节来进行传输,我来为大家科普一下关于netty客户端发送数据并接收返回值?以下内容希望对你有帮助!

netty客户端发送数据并接收返回值

简介

我们知道由两种数据的传输方式,分别是字符流和字节流,字符流的意思是传输的对象就是字符串,格式已经被设置好了,发送方和接收方按照特定的格式去读取就行了,而字节流是指将数据作为最原始的二进制字节来进行传输。

今天给大家介绍一下在netty中的基于流的数据传输。

package和byte

熟悉TCP/IP协议的同学应该知道,在TCP/IP中,因为底层协议有支持的数据包的最大值,所以对于大数据传输来说,需要对数据进行拆分和封包处理,并将这些拆分组装过的包进行发送,最后在接收方对这些包进行组合。在各个包中有固定的结构,所以接收方可以很清楚的知道到底应该组合多少个包作为最终的结果。

那么对于netty来说,channel中传输的是ByteBuf,实际上最最最底层的就是byte数组。对于这种byte数组来说,接收方并不知道到底应该组合多少个byte来合成原来的消息,所以需要在接收端对收到的byte进行组合,从而生成最终的数据。

那么对于netty中的byte数据流应该怎么组合呢?我们接下来看两种组合方法。

手动组合

这种组合的方式的基本思路是构造一个目标大小的ByteBuf,然后将接收到的byte通过调用ByteBuf的writeBytes方法写入到ByteBuf中。最后从ByteBuf中读取对应的数据。

比如我们想从服务端发送一个int数字给客户端,一般来说int是32bits,然后一个byte是8bits,那么一个int就需要4个bytes组成。

在server端,可以建立一个byte的数组,数组中包含4个元素。将4个元素的byte发送给客户端,那么客户端该如何处理呢?

首先我们需要建立一个clientHander,这个handler应该继承ChannelInboundHandlerAdapter,并且在其handler被添加到ChannelPipeline的时候初始化一个包含4个byte的byteBuf。

handler被添加的时候会触发一个handlerAdded事件,所以我们可以这样写:

private ByteBuf buf;@Overridepublic void handlerAdded(ChannelHandlerContext ctx) {//创建一个4个byte的缓冲器buf = ctx.alloc().buffer(4);}

上例中,我们从ctx分配了一个4个字节的缓冲器,并将其赋值给handler中的私有变量buf。

当handler执行完毕,从ChannelPipeline中删除的时候,会触发handlerRemoved事件,在这个事件中,我们可以对分配的Bytebuf进行清理,通常来说,可以调用其release方法,如下所示:

public void handlerRemoved(ChannelHandlerContext ctx) {buf.release(); // 释放bufbuf = null;}

然后最关键的一步就是从channel中读取byte并将其放到4个字节的byteBuf中。在之前的文章中我们提到了,可以在channelRead方法中,处理消息读取的逻辑。

public void channelRead(ChannelHandlerContext ctx, Object msg) {ByteBuf m = (ByteBuf) msg;buf.writeBytes(m); // 写入一个bytem.release();if (buf.readableBytes() >= 4) { // 已经凑够4个byte,将4个byte组合称为一个intlong result = buf.readUnsignedInt();ctx.close();}}

每次触发channelRead方法,都会将读取到的一个字节的byte通过调用writeBytes方法写入buf中。当buf的可读byte大于等于4个的时候就说明4个字节已经读满了,可以对其进行操作了。

这里我们将4个字节组合成一个unsignedInt,并使用readUnsignedInt方法从buf中读取出来组合称为一个int数字。

上面的例子虽然可以解决4个字节的byte问题,但是如果数据结构再负责一点,上面的方式就会力不从心,需要考虑太多的数据组合问题。接下来我们看另外一种方式。

Byte的转换类

netty提供了一个ByteToMessageDecoder的转换类,可以方便的对Byte转换为其他的类型。

我们只需要重新其中的decode方法,就可以实现对ByteBuf的转换:

public class SquareDecoder extends ByteToMessageDecoder {@Override public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out)throws Exception {out.add(in.readBytes(in.readableBytes())); }}

上面的例子将byte从input转换到output中,当然,你还可以在上面的方法中进行格式转换,如下所示:

public class TimeDecoder extends 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操作和变换的几种方式,希望大家能够喜欢。

    推荐阅读
  • 广东省新建沿海高速(广东粤北新建出省高速公路)

    近日,从广东省交通有关部门发布的消息可知:武深高速公路始兴联络线项目初步设计文件顺利通过评审。据悉,武深高速公路始兴联络线是粤北山区通往江西方向的又一出省通道。武深高速公路始兴联络线起于罗坝镇深渡水乡坪田村,设深渡水枢纽互通立交接武深高速仁化至博罗段,往东北经顿岗镇,终于马市镇,设关桥枢纽互通立交接韶赣高速公路,路线全长29.42公里。采用双向4车道高速公路技术标准,设计速度100公里/小时,路基宽度26.5米。

  • 蛙泳一千米及格时间(蛙泳两千米及格时间)

    1000米蛙泳也不是比赛项目,因此无从判断。这其中包括了个人体重、游泳速度等。蛙泳的翻脚蹬夹水动作对于膝关节是有一定损伤的。因此,从这以方面上来说,蛙泳又不适宜长期的进行,与减肥要求相向而行。有氧运动初期,体内脂肪燃烧较少,很多能量是糖类和蛋白质提供的。因此,蛙泳应当持续到30分钟以上。但如果运动时间过长,身体过于疲累,而且也会消耗过多蛋白质,导致肌肉流失。因此,最长也不应该超过2小时。

  • 于月仙车祸责任人确定(于月仙车祸肇事者被判1年)

    8月9日,著名演员于月仙去世一周年,其丈夫张学松导演在社交平台发文悼念亡妻,并爆料了车祸案情的最新进展!交通肇事者郭某因交通肇事罪,被判处有期徒刑一年,自2022年4月15日起至2023年4月14日,于鄂尔多斯监狱服刑。2021年8月9日,于月仙在内蒙古自治区拍戏不幸遭遇车祸,不治身亡!于月仙老公张雪松发文称,一年里不同的想念,共同的怀念。于月仙车祸案件牵涉的单位较多,比较复杂,受疫情影响,但是还是在一步步推进中。

  • 告别朋友圈的心情短语(告别朋友圈的心情短语有哪些)

    告别朋友圈的心情短语?跟着小编一起来看一看吧!关于这个朋友圈,我最终还是离开了。没有故事,没有爱人,单枪匹马也懒的热闹。没有什么可以牵挂的了,这个朋友圈退得利落。世界只有一个我,你再也不会遇见第二个。我的满心欢喜,该告一段落了。你我从此,天涯陌路,后会无期。世界再美的风景,都不及回家的那段路。一座城市,一次离别。退朋友圈求安稳,从此与世无争,再见。还是先消失一段时间吧。

  • 职业类工资排行榜(最新工资价位表来了)

    职业类工资排行榜中新网9月20日电人社部近日发布2021年企业薪酬调查信息,披露了工资价位数据。它表示有相应比例的数据低于或等于该数值。中新财经注意到,除了高位数外,在其他分位的工资水平方面,金融服务人员均为最高,高于其他职业。除了不同职业企业从业人员工资价位,不同岗位等级企业从业人员工资价位数据也一并公布。这张表包括管理类岗位等级、技术类岗位等级、技能类岗位等级三类。

  • 感染诺如病毒后需要隔离多长时间(诺如病毒感染途径主要有三)

    截止到14日20时,52件标本检测出诺如病毒,其他标本尚在检测中。诺如病毒目前已被欧美国家公认为是导致成人病毒性腹泻及急性胃肠炎的首要病因,在儿童病毒性腹泻中仅次于轮状病毒。有的国家将其称之为“胃流感”。儿童和老人发病率较高。诺如病毒一般在感染后12至48小时出现症状。诺如病毒患者如出现呕吐、腹泻症状,可根据需要采用口服补盐液进行治疗,脱水严重者应及时就医。

  • ai保存jpg格式(上传jpg格式文件图片的方法)

    而AI和小程序的结合,在提高工作效率上,会有更大的潜力。我们不用掌握任何设计基础,输入文字需求,ARKIE就能自动分析语意,进行图文匹配、智能裁切、排版布局和修饰配色等。体验下来,我发现它的「知识与语义」中的「情绪倾向分析」能读懂很多话外之音!!从这些优秀良心的AI小程序上,我们也能看到AI人工智能的发展前景潜力无限,非常值得我们去期待。

  • 什么运动方法瘦得快(怎么运动才能瘦得快)

    因为有氧运动可以促进脂肪的分解,但是无法强化身体肌群。03重视体脂率,而不是体重刚开始健身的时候,如果你只关注体重,很容易陷入误区。因为减肥的关键是减脂,而不是减重。而肌肉的生长会导致体重上升,但是这不意味着你变胖了。因此,减肥期间,你要测量的是自身的体脂率,而不是体重。健身不仅可以让你保持一副好身材,还能有效强身健体,抵抗衰老速度。

  • 抖音怎么边拍边关美颜(抖音里关美颜怎么拍)

    抖音边拍边关美颜的方法如下:1、首先打开抖音app,然后点击屏幕下方的“+”图标。抖音,是一款可以拍摄短视频的音乐创意短视频社交软件,该软件于2016年9月上线,是一个专注年轻人音乐短视频社区平台。用户可以通过这款软件选择歌曲,拍摄音乐短视频,形成自己的作品。

  • 舞蹈考级年龄和级别(舞蹈考级年龄和级别是什么)

    下面内容希望能帮助到你,我们来一起看看吧!舞蹈考级年龄和级别舞蹈考级是有年龄限制的,年龄不足不能考。舞蹈考级共分13级,适用年龄分别为:一级4-5岁、二级5-6岁、三级6-7岁、四级7-9岁、五级8-10岁、六级9-11岁、七级10-12岁、八级11-13岁、九级12-14岁、十级13-15岁、十一级14-16岁、十二级15-17岁、十三级16-18岁。