Netty:DelimiterBasedFrameDecoder分析

news2024/11/26 2:53:28

说明

io.netty.handler.codec.DelimiterBasedFrameDecoder是ByteToMessageDecoder的一个实现类,用一个或多个分割符拆分接收到的 ByteBuf。这个主要用于解析分隔符在帧的末尾的情况。注意,如果分割符在帧的开头,那么解析出来的帧的长度是0,所以要用在末尾的分隔符。
在构造DelimiterBasedFrameDecoder实例的时候,用到了下面几个参数,用来控制拆分行为:

  • maxFrameLength:拆分的帧最多有多少字节。
  • stripDelimiter:拆分后的帧是否去掉分隔符,默认值为true。
  • failFast:默认值为true。当为true的时候,如果解码器发现帧的长度大于maxFrameLength,就会抛出 TooLongFrameException,而不管是否真正读取了整个帧。如果值为false,实际读取的字节数大于maxFrameLength时,才会抛出TooLongFrameException。
  • delimiters:多个分割符。
  • delimiter:单个分割符。

代码示例

分割符在报文的结尾,正常解析

本示例验证的场景:

  • 客户端发送了一个12字节的报文给服务端。报文开头的字节内容是0x68,结尾的字节内容是0x16。
  • 服务端用了DelimiterBasedFrameDecoder来基于分隔符解析帧。解析的时候设置帧的最大字节数是12,去掉分隔符,分隔符是0x16。解析完成后,将去掉分隔符的帧传送给后面的ChannelHandler。

服务端代码片段

package com.thb.power.server;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

/**
 * 服务端的主函数
 * @author thb
 *
 */
public class MainStation {
	private static final Logger logger = LogManager.getLogger();
	
	static final int PORT = Integer.parseInt(System.getProperty("port", "22335"));

	public static void main(String[] args) throws Exception {
		logger.traceEntry();
		
		// 配置服务器
		EventLoopGroup bossGroup = new NioEventLoopGroup();
		EventLoopGroup workerGroup = new NioEventLoopGroup();
		try {
			ServerBootstrap b =  new ServerBootstrap();
			b.group(bossGroup, workerGroup)
			 .channel(NioServerSocketChannel.class)
			 .option(ChannelOption.SO_BACKLOG, 100)
			 .handler(new LoggingHandler(LogLevel.INFO))
			 .childHandler(new MainStationInitializer());
			
			// 启动服务端
			ChannelFuture f = b.bind(PORT).sync();
			
			// 等待直到server socket关闭
			f.channel().closeFuture().sync();
		} finally {
			// 关闭所有event loops以便终止所有的线程
			bossGroup.shutdownGracefully();
			workerGroup.shutdownGracefully();
		}
		
		logger.traceExit();
	}

}
package com.thb.power.server;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.thb.power.server.register.ServerRegisterRequestHandler;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

public class MainStationInitializer extends ChannelInitializer<SocketChannel> {
	private static final Logger logger = LogManager.getLogger();

	 @Override
	 public void initChannel(SocketChannel ch) throws Exception {
		 logger.traceEntry();
		 
		 ChannelPipeline p = ch.pipeline();		
		 
		 p.addLast(new LoggingHandler(LogLevel.INFO));
		 p.addLast(new DelimiterBasedFrameDecoder(12, true, Unpooled.wrappedBuffer(new byte[] {0x16})));
		 p.addLast(new ServerRegisterRequestHandler());
		 
		 logger.traceExit();
	 }
}
package com.thb.power.server.register;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

public class ServerRegisterRequestHandler extends ChannelInboundHandlerAdapter {
	
	private static final Logger logger = LogManager.getLogger();
	
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) {
		logger.traceEntry();
		
		ByteBuf m = (ByteBuf)msg;
		
		logger.info("readableBytes: " + m.readableBytes());
		logger.traceExit();
	}
	
	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		cause.printStackTrace();
		ctx.close();
	}
}

启动服务端

在这里插入图片描述

启动客户端,并向服务端发送包含12个字节的报文

在这里插入图片描述

观察服务端的输出

在这里插入图片描述
从服务端的输出可以看到,ServerRegisterRequestHandler收到了11个字节的数据,这是正确的。因为整个帧12个字节,DelimiterBasedFrameDecoder在解析的时候,我们通过参数控制,去掉了1个字节的分隔符。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/872845.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从一到无穷大 #10 讨论 Apache IoTDB 大综述中看到的优劣势

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。 本作品 (李兆龙 博文, 由 李兆龙 创作)&#xff0c;由 李兆龙 确认&#xff0c;转载请注明版权。 文章目录 引言问题定义新技术数据模型schemalessTsfile设计双MemTable高级可扩展查询其他 IotD…

如何实现浅拷贝和深拷贝

一、浅拷贝的实现方法 1.Object.assign方法 let obj1{name:"aaa",}let obj2{age:20}let obj3Object.assign(obj1,obj2)// obj3.age30console.log(obj1);console.log(obj3);console.log(obj1obj3);console.log(obj1obj3); 结果为&#xff1a; 2.直接赋值 let obj1{n…

sql中union all、union、intersect、minus的区别图解,测试

相关文章 sql 的 join、left join、full join的区别图解总结&#xff0c;测试&#xff0c;注意事项 1. 结论示意图 对于intersect、minus&#xff0c;oracle支持&#xff0c;mysql不支持&#xff0c;可以变通&#xff08;in或exists&#xff09;实现 2.测试 2.1.创建表和数…

将Map存到数据库中,并且支持数据类型原样取回

1.数据库设计 1.1 表设计 create table variables (id bigint not null comment 主键,business_key varchar(128) null comment 业务key,data_key varchar(128) null comment Map中的key,data_value varchar(…

35岁职业危机?不存在!体能断崖?不担心

概述 90年&#xff0c;硕士毕业&#xff0c;干了快8年的Java开发工作。现年33岁&#xff0c;再过2年就要35岁。 工作这些年&#xff0c;断断续续也看过不少35岁找不到工作&#xff0c;转行&#xff0c;降薪入职的传闻、案例。 35岁&#xff0c;甚至30岁之后&#xff0c;体能…

【Linux操作系统】文件描述符fd

&#x1f525;&#x1f525; 欢迎来到小林的博客&#xff01;&#xff01;       &#x1f6f0;️博客主页&#xff1a;✈️林 子       &#x1f6f0;️博客专栏&#xff1a;✈️ Linux之路       &#x1f6f0;️社区 :✈️ 进步学堂       &#x1…

easyx图形库基础:1.基本概念的介绍+图形的绘制。

基本概念的介绍图形的绘制 一.基本概念的介绍。1.为什么要使用easyx图形库2.安装easyx图形库。3.语法相关 二.图形绘制1.窗体创建和坐标的概念。1.基本窗体的创建。2.坐标概念3.改变逻辑坐标。 2.设置图形颜色1.设置描边颜色和描边样式。2.设置图形填充颜色和填充样式3.绘制图形…

【第二阶段】kotlin的函数类型作为返回类型

fun main() {//调用,返回的是一个匿名类型&#xff0c;所以info就是一个匿名函数val infoshow("",0)//info接受的返回值为匿名类型&#xff0c;此时info就是一个匿名函数println(info("kotlin",20)) }//返回类型为一个匿名函数的返回类型fun show(name:Str…

编程工具合集

须知&#xff1a; 本博文只是为了记录程序员在编程中所用到的编程工具以及效率软件&#xff0c;如有侵权&#xff0c;请告知&#xff01; VSCode 英文官网&#xff1a;https://code.visualstudio.com/ 中文官网&#xff1a;http://vscode.p2hp.com/ win下载链接&#xff1a;VS…

ModaHub魔搭社区:AI时代连接硬件和上层应用的中间层基础设施。

从类比的角度理解AI Infra:AI时代连接硬件和上层应用的中间层基础设施。传统本地部署时代,三大基础软件(数据库、操作系统、中间件)实现控制硬件交互、存储管理数据、网络通信调度等共性功能,抽象并隔绝底层硬件系统的复杂性,让上层应用开发者能够专注于业务逻辑和应用功…

Kotlin入门:变量和函数——02

目录 一、Kotlin 基本数据类型 ​编辑 二、变量 val 关键字&#xff1a; var 关键字: 类型推断: 可空类型: 三、函数 基本函数语法&#xff1a; 单表达式函数&#xff1a; 默认参数值&#xff1a; 命名参数&#xff1a; 一、Kotlin 基本数据类型 Kotlin 的基本数…

CCLINK IE 转MODBUS-RTU网关modbusrtu与485区别

远创智控YC-CCLKIE-RTU。这款产品的主要功能是将各种MODBUS-RTU、RS485、RS232设备接入到CCLINK IE FIELD BASIC网络中。 那么&#xff0c;这款通讯网关又有哪些特点呢&#xff1f;首先&#xff0c;它能够连接到CCLINK IE FIELD BASIC总线中作为从站使用&#xff0c;同时也能连…

sqlyog下载和卸载的最新详细过程,超多图快速安装或者卸载

目录 1.SQLyog的介绍2.sqlyog的下载和安装3.sqlyog的卸载 ✨ 原创不易&#xff0c;还希望各位大佬支持一下&#xff01; &#x1f44d; 点赞&#xff0c;你的认可是我创作的动力&#xff01; ⭐️ 收藏&#xff0c;你的青睐是我努力的方向&#xff01; ✏️ 评论&#xff0c…

7.5.tensorRT高级(2)-RAII接口模式下的生产者消费者多batch实现

目录 前言1. RAII接口模式封装生产者消费者2. 问答环节总结 前言 杜老师推出的 tensorRT从零起步高性能部署 课程&#xff0c;之前有看过一遍&#xff0c;但是没有做笔记&#xff0c;很多东西也忘了。这次重新撸一遍&#xff0c;顺便记记笔记。 本次课程学习 tensorRT 高级-RAI…

Netty核心源码解析(一)

Netty是什么&#xff1f; Netty是Jboss提供的一个Java 开源框架&#xff0c;主要针对TCP协议的高并发场景Netty本质是对Java NIO做了封装的网络通信框架&#xff0c;主要作用是Java NIO基本接口的封装&#xff0c;提供了网络通信中线程同步&#xff0c;编解码&#xff0c;粘包拆…

小龟带你敲排序之冒泡排序

冒泡排序 一. 定义二.题目三. 思路分析&#xff08;图文结合&#xff09;四. 代码演示 一. 定义 冒泡排序&#xff08;Bubble Sort&#xff0c;台湾译为&#xff1a;泡沫排序或气泡排序&#xff09;是一种简单的排序算法。它重复地走访过要排序的数列&#xff0c;一次比较两个元…

Kettle系列(一)下载安装与基础配置

Kettle系列&#xff08;一&#xff09;下载安装与基础配置 说明一、下载二、目录结构三、基础配置&#xff08;1&#xff09;环境变量&#xff08;2&#xff09;kettle配置 四、连接mysql8五、连接其他数据库六、总结 说明 更新时间&#xff1a;2023/08/13 17:47 本文记录了wi…

openGauss学习笔记-38 openGauss 高级数据管理-游标

文章目录 openGauss学习笔记-38 openGauss 高级数据管理-游标38.1 语法格式38.2 参数说明38.3 示例 openGauss学习笔记-38 openGauss 高级数据管理-游标 为了处理SQL语句&#xff0c;存储过程进程分配一段内存区域来保存上下文联系。游标是指向上下文区域的句柄或指针。借助游…

【Pytroch】基于决策树算法的数据分类预测(Excel可直接替换数据)

【Pytroch】基于决策树算法的数据分类预测&#xff08;Excel可直接替换数据&#xff09; 1.模型原理2.数学公式3.文件结构4.Excel数据5.下载地址6.完整代码7.运行结果 1.模型原理 决策树是一种常用的机器学习算法&#xff0c;用于分类和回归任务。它通过树状结构表示数据的决策…

Opencv4基于C++的 实时人脸检测

文章目录: 一&#xff1a;环境配置搭建(VS2015Opencv4.6) 二&#xff1a;下资源文件 第一种&#xff1a;本地生成 第二种 直接下载 三&#xff1a;代码展示 窗口布局 main.cpp test.h test.cpp 效果图◕‿◕✌✌✌&#xff1a;opencv人脸识别效果图(请叫我真爱粉) 一&…