游戏攻略网
当前位置: 首页 游戏攻略

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

    推荐阅读
  • steam棋牌游戏推荐(幸运之夜新版本亮相TGC)

    steam棋牌游戏推荐12月1日,2017腾讯游戏嘉年华正式在成都开幕,腾讯的VR社交游戏《幸运之夜》在现场发布了最新版本。VR《幸运之夜》在TGC2017上惊艳亮相《幸运之夜》新版本发布邀请好友一起游戏今年7月底,《幸运之夜》正式在Steam发布,并推出了首款游戏作品“德州扑克”。今年的TGC2017现场,《幸运之夜》全新版本便带来了对互动性方面的提升。

  • 儿童睡前故事卖火柴的小女孩大全(卖火柴的小女孩)

    在长发公主的故事里,兔子小姐变成了手持宝剑的骑士,穿过了山川和河流,战胜了地狱恶犬,最终救出了长着一头金黄色长发的熊猫先生。随着一阵空间的波动,熊猫先生和兔子小姐来到了冰天雪地的圣诞节。小女孩被这突如其来的变化惊呆了。熊猫先生没有回答,轻轻摸了摸小女孩的头。小女孩点燃了第二根火柴。熊猫先生和兔子小姐则来到壁炉前,商量起小女孩最后一个愿望。熊猫先生蹲下来,握起小女孩的手。

  • 怎样做ppr管快一点(PPR管安装方法及技巧)

    怎样做ppr管快一点PPR管安装方法及技巧首先准备好需要的材料:热熔机,小剪刀,ppr管,管件,手巾。一定要根据自己热熔ppr管的口径,准备相应的热熔头。清洁:清洁管材与管件的焊接段部位,建议用95%浓度酒精擦净。在熔接时间内迅速的将管材无旋转的垂直插入管件中,并维持5秒以上,然后按相应冷却时间冷却。热熔后做到横平竖直,美观大方。

  • 大托特包搭配技巧(大托特包搭配技巧简述)

    西装外套+托特包复古时尚的格子,由黑白交错的条纹形成,文艺而又端庄搭配撞色托特包,优雅而不失俏皮,让气场变得灵动起来内搭白色连帽卫衣,减龄又可爱,接下来我们就来聊聊关于大托特包搭配技巧?大托特包搭配技巧西装外套+托特包复古时尚的格子,由黑白交错的条纹形成,文艺而又端庄。衬衫+托特包白色的衬衫休闲慵懒,给人一种空灵的感觉以及干净纯粹的气质。

  • 刘涛电视剧口碑(电视剧景气指数第一)

    还记得3月份刘涛在和周渝民主演的《大宋宫词》中扮嫩出演少妇被很多观众吐槽。万万没想到时隔数月,刘涛带着她的新剧《星辰大海》杀回来了。目前主要的剧情线在刘涛饰演的女主简爱身上。因为小时候意外发现母亲出轨的事,得知真相的父亲激愤之下杀死母亲并自杀,简爱因此成为了一个孤女。逃出傻子家的简爱在与姑姑的争执中误伤姑姑,从此开启逃命生涯。简爱从面馆辞职走投无路,误打误撞进入大公司之后面临着同事的故意刁难。

  • 外墙装修材料有哪些 外墙装修材料有哪些类型

    外墙涂料具有装饰性良好、耐污染耐老化以及施工维修容易和价格合理的特点。一般来说釉面外墙砖有亚光面与无光面两大类。它的装饰的效果也不错,有柚木色、深灰色等等可供选择。由于它的表面的肌理很清晰,所以色泽漂亮且装饰性极强。本站,中国知名大型装修平台,装修领导品牌。

  • 世界上有哪些花(世界上有哪些花 名字)

    瓜叶菊、香豌豆、夏兰、石竹、石蒜、荷花、翠菊、睡莲、福禄考、晚香玉、万寿菊、千日红、建兰、铃兰、报岁兰、香堇、大岩桐、水仙、小草兰、瓜叶菊、蒲包花、免子花、入腊红、三色堇、百日草、鸡冠花、一串红。孔雀草、大波斯菊、金盏菊、非洲凤仙花、菊花、非洲菊、观赏凤梨类、射干、非洲紫罗兰、天堂鸟、炮竹红、菊花、康乃馨、红掌、满天星、星辰花、三角梅、虞美人。

  • 长歌行李长歌母亲是谁杀的(长歌行李长歌的简介)

    下面更多详细答案一起来看看吧!长歌行李长歌母亲是谁杀的《长歌行》李长歌母亲是自杀的。李长歌,太子李建成之女,生母则是回纥王族。父母手足均死于玄武门之变,满怀愤恨的长歌凭高超武艺逃出皇宫,并在追捕过程中制造“坠崖假死”而逃生,其后女扮男装隐瞒身份流落民间,一心只想为父母复仇,在家和国的利害冲突中,最后放弃复仇,和阿诗勒隼一起成为了民族和解的使者。

  • 什么时候喝蛋白粉增肌效果最好(什么时候喝蛋白粉增肌效果最好)

    从长远来看,这种方法被证明可以促使肌肉明显增长。如果摄入量超过一定的阈值,蛋白质的合成就会受限。如果是以乳清饮料的形式摄入乳清蛋白,运动者可以在运动结束后立即饮用。按每公斤体重1克的标准,在健身前后立即摄入以及在运动后1小时内摄入可快速吸收的碳水化合物,可以明显抑制肌肉分解,并大大促进肌肉快速和明显的增长。在这种情况下,大量分泌的胰岛素促进了氨基酸向工作中的肌肉运输,为蛋白质合成奠定基础。

  • 窦骁周冬雨山楂树之恋结局(周冬雨18岁第一次出演)

    周冬雨18岁第一次出演要说最近最火的电影,非《少年的你》莫属,上映14天,已经收获了12.45亿的票房成绩,成为现阶段最强的票房黑马而作为该片主演的周冬雨和易烊千玺,也凭借在该片中的精彩演出,演技得到大众的进一步认可作为“。