首页 > 编程语言 >Java NIO框架Netty教程(四)- ChannelBuffer

Java NIO框架Netty教程(四)- ChannelBuffer

时间:2024-07-26 10:54:28浏览次数:21  
标签:Netty Java NIO stream received buffer ChannelBuffer +-----+-----+-----+

字符串消息收发中提到。ChannelBufferNetty中非常重要的概念。所有消息的收发都依赖于这个Buffer。我们通过Netty的官方的文档来了解一下,基于流的消息传递机制。

In a stream-based transport such as TCP/IP, received data is stored into a socket receive buffer.

Unfortunately, the buffer of a stream-based transport is not a queue of packets but a queue of bytes. It

means, even if you sent two messages as two independent packets, an operating system will not treat them

as two messages but as just a bunch of bytes. Therefore, there is no guarantee that what you read is exactly

what your remote peer wrote. For example, let us assume that the TCP/IP stack of an operating system has

received three packets:

+-----+-----+-----+

| ABC | DEF | GHI |

+-----+-----+-----+

Because of this general property of a stream-based protocol, there' high chance of reading them in the

following fragmented form in your application:

+----+-------+---+---+

| AB | CDEFG | H | I |

+----+-------+---+---+

Therefore, a receiving part, regardless it is server-side or client-side, should defrag the received data into one

or more meaningful frames that could be easily understood by the application logic. In case of the example

above, the received data should be framed like the following:

+-----+-----+-----+

| ABC | DEF | GHI |

+-----+-----+-----+

</div>

您理解了没,简单翻译一下就是说。在TCP/IP这种基于流传递的协议中。他识别的不是你每一次发送来的消息,不是分包的。而是,只认识一个整体的流,即使分三次分别发送三段话:ABCDEFGHI。在传递的过程中,他就是一个具有整体长度的流。在读流的过程中,如果我一次读取的长度选择的不是三个,我可以收到类似ABCDEFGHI这样的信息。这显然是我们不想看到的。所以说,在你写的消息收发的系统里,需要预先定义好这种解析机制,规定每帧(次)读取的长度。通过代码来理解一下:

全文详见个人独立博客:https://www.coderli.com/netty-channel-stream/

Java NIO框架Netty教程(四)- ChannelBuffer在字符串消息收发中提到。ChannelBuffer是Netty中非常重要的概念。所有消息的收发都依赖于这个Buffer。我们通过Netty的官方的文档来了解一下,基于流的消息传递机制。 In a stream-based transport such as TCP/IP, received data is stored into a socket receive buffer. Unfortunately, the buffer of a stream-based transport is not a queue of packets but a queue of bytes. It means, even if you sent two messages as two independent packets, an operating system will not treat them as two messages but as just a bunch of bytes. Therefore, there is no guarantee that what you read is exactly what your remote peer wrote. For example, let us assume that the TCP/IP stack of an operating system has received three packets: +-----+-----+-----+ | ABC | DEF | GHI | +-----+-----+-----+ Because of this general property of a stream-based protocol, there' high chance of reading them in the following fragmented form in your application: +----+-------+---+---+ | AB | CDEFG | H | I | +----+-------+---+---+ Therefore, a receiving part, regardless it is server-side or client-side, should defrag the received data into one or more meaningful frames that could be easily understood by the application logic. In case of the example above, the received data should be framed like the following: +-----+-----+-----+ | ABC | DEF | GHI | +-----+-----+-----+ </div> 您理解了没,简单翻译一下就是说。在TCP/IP这种基于流传递的协议中。他识别的不是你每一次发送来的消息,不是分包的。而是,只认识一个整体的流,即使分三次分别发送三段话:ABC、DEF、GHI。在传递的过程中,他就是一个具有整体长度的流。在读流的过程中,如果我一次读取的长度选择的不是三个,我可以收到类似AB、CDEFG、H、I这样的信息。这显然是我们不想看到的。所以说,在你写的消息收发的系统里,需要预先定义好这种解析机制,规定每帧(次)读取的长度。通过代码来理解一下: /** * @author lihzh * @alia OneCoder * @blog http://www.coderli.com */ public class ServerBufferHandler extends SimpleChannelHandler { /** * 用户接受客户端发来的消息,在有客户端消息到达时触发 * * @author lihzh * @alia OneCoder */ @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) { ChannelBuffer buffer = (ChannelBuffer) e.getMessage(); // 五位读取 while (buffer.readableBytes() >= 5) { ChannelBuffer tempBuffer = buffer.readBytes(5); System.out.println(tempBuffer.toString(Charset.defaultCharset())); } // 读取剩下的信息 System.out.println(buffer.toString(Charset.defaultCharset())); } } /** * @author lihzh * @alia OneCoder * @blog http://www.coderli.com */ public class ClientBufferHandler extends SimpleChannelHandler { /** * 当绑定到服务端的时候触发,给服务端发消息。 * * @alia OneCoder * @author lihzh */ @Override public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) { // 分段发送信息 sendMessageByFrame(e); } /** * 将<b>"Hello, I'm client."</b>分成三份发送。 <br> * Hello, <br> * I'm<br> * client.<br> * * @param e * Netty事件 * @author lihzh */ private void sendMessageByFrame(ChannelStateEvent e) { String msgOne = "Hello, "; String msgTwo = "I'm "; String msgThree = "client."; e.getChannel().write(tranStr2Buffer(msgOne)); e.getChannel().write(tranStr2Buffer(msgTwo)); e.getChannel().write(tranStr2Buffer(msgThree)); } /** * 将字符串转换成{@link ChannelBuffer},私有方法不进行字符串的非空判断。 * * @param str * 待转换字符串,要求非null * @return 转换后的ChannelBuffer * @author lihzh */ private ChannelBuffer tranStr2Buffer(String str) { ChannelBuffer buffer = ChannelBuffers.buffer(str.length()); buffer.writeBytes(str.getBytes()); return buffer; } } 服务端输出结果: Hello , I'm clie nt. 这里其实,服务端是否分段发送并不会影响输出结果,也就是说,你一次性的把”Hi, I’m client.”这段信息发送过来,输出的结果也是一样的。这就是开头说的,传输的是流,不分包。而只在于你如何分段读写。icon-default.png?t=N7T8https://www.coderli.com/netty-channel-stream/交流探讨,加入群聊【Java学习交流(982860385)】

标签:Netty,Java,NIO,stream,received,buffer,ChannelBuffer,+-----+-----+-----+
From: https://blog.csdn.net/CoderCoding/article/details/140679131

相关文章

  • Java NIO框架Netty教程(六)-Java NIO Selector模式
    全文详见个人独立博客:JavaNIO框架Netty教程(六)-JavaNIOSelector模式JavaNIO框架Netty教程(六)-JavaNIOSelector模式看到标题,您可能觉得,这跟Netty有什么关系呢?确实,如果你完全是使用Netty的,那么可能你可以完全不需要了解Selector。但是,不得不提的是,Netty底层关于NIO的实......
  • (Javaweb)Vue
    目录一.Vue概述二Vue指令三.vue生命周期一.Vue概述1.model--数据模型:包含了很多的业务数据以及数据的处理方法2.view--视图层--数据的展示--DOM元素3.viewmodel--完成数据绑定的核心,实现model与viewmodel之间的数据连接其中,MVVM由三部分组成,model,view,viewmodelm......
  • (Javaweb)js
    目录一.js介绍二.引入方式三.js基础语法1.书写语法2.js变量3.数据类型运算符流程控制语句 四.js函数五.js对象六.js对象--Array数组七js对象--String字符串八.js对象--JSON九.js对象--BOM十.js对象--DOMDOM案例一.js介绍脚本语言:代码不需要进行编译,直......
  • JavaScript 基础
    JavaScript简介JavaScript是一种具有函数优先原则的轻量级、解释型、即时编译型的编程语言。函数优先原则:函数可以和其他任何变量一样对待,而且函数的优先级会被提升。.轻量级:语法和Java类似,语法简单易学。解释型:代码在运行时直接由解释器逐行解释和执行,而不需要事先将......
  • Java毕业设计-基于springboot开发的ONLY在线商城系统设计与开发-代码-毕业论文(附毕设
    文章目录前言一、毕设成果演示(源代码在文末)二、毕设摘要展示1、开发说明2、需求/流程分析3、系统功能结构三、系统实现展示1、用户信息管理2、商品分类管理3、商品信息管理4、轮播图管理四、毕设内容和源代码获取总结Java毕业设计-基于springboot开发的ONLY在线商......
  • Java毕业设计-基于springboot开发的在线课程管理系统-毕业论文(附毕设源代码)
    文章目录前言一、毕设成果演示(源代码在文末)二、毕设摘要展示1、开发说明2、需求/流程分析3、系统功能结构三、系统实现展示1、管理员模块的实现1.1教师信息管理1.2学生信息管理1.3在线课程管理1.4班级分类管理2、教师模块的实现2.1在线课程信息2.2教学计划管理2.......
  • 终端输入mvn -v报错:JAVA_HOME not found in your environment.
    终端输入mvn-v报错:JAVA_HOMEnotfoundinyourenvironment.       原因在于jdk环境变量未配置好。环境变量设置有如下两种方法:1、右键我的电脑-->属性-->高级系统设置-->环境变量-->系统变量-->双击Path-->点击新建-->输入jdk本地路径(如:D:\Tools\jdk1.8.0_121\bin)-......
  • java题目之金额转换以及如何优化
    publicclassScannerDemo5{publicstaticvoidmain(String[]args){//键盘录入一个金额intmoney;while(true){System.out.println("请输入一个金额:");Scannersc=newScanner(System.in);mon......
  • java环境变量的配置
    1.path环境变量配置的作用程序的执行需要使用外部指令javac,但是javac指令仅仅能在JDK安装目录下的bin目录下时候,因此程序只能写入bin目录程序开发过程中,不能将源代码写入JDK的安装目录,因此需要将源程序保存到任意位置的指定目录(英文目录),所以需要使javac指令在任意目录下可以运......
  • JAVA编译和运行的CMD命令
    JAVA编译和运行的CMD命令编译JAVA程序编译Java程序是将源代码文件(.java)转换为字节码文件(.class)的过程。在CMD中,我们可以使用javac命令来进行编译。命令格式:javac[选项]文件名.java运行JAVA程序编译完成后,你可以使用java命令来运行生成的字节码文件。命令格式:java[选项]......