网络编程-编码与解码(Protobuf)

编码与解码

下面的文字都来自于极客时间
为什么要编解码呢?因为计算机数据传输的是二进制的字节数据
解码:字节数据 --> 字符串(字符数据)
编码:字符串(字符数据)–> 字节数据

我们在编写网络应用程序的时候需要注意 codec (编解码器),因为数据在网络中传输的都是二进制字节
码数据,而我们拿到的目标数据往往不是字节码数据。因此在发送数据时就 需要编码,接收数据时就需
要解码。
codec 的组成部分有两个:decoder(解码器)和 encoder(编码器)。

  • encoder 负责把业务数据转换成字节码数据
  • decoder 负责把字节码数据转换成业务数据
    其实 Java 的序列化技术就可以作为 codec 去使用,但是它的硬伤太多:
  1. 无法跨语言,这应该是 Java 序列化最致命的问题了
  2. 序列化后的体积太大,是二进制编码的 5 倍多
  3. 序列化性能太低

Netty 自身提供了一些 编解码器,如下:

  • StringEncoder对字符串数据进行编码
  • ObjectEncoder对 Java 对象进行编码

Netty 本身自带的 ObjectDecoder 和 ObjectEncoder 可以用来实现 POJO 对象或各种业务对象的编码和解码,但其内部使用的仍是 Java 序列化技术,所以在某些场景下不适用。对于 POJO 对象或各种业务对象要实现编码和解码,我们需要更高效更强的技术。由此引出:Google 的 Protobuf。

Google 的 Protobuf

Protobuf 是 Google 发布的开源项目,全称 Google Protocol Buffers,特点如下:支持跨平台、多语言(支持目前大多数语言,例如 C++、C#、Java、python 等)高性能,高可靠性。
使用 protobuf 编译器能自动生成代码,Protobuf 是将类的定义使用.proto 文件进行描述,然后通过 protoc.exe 编译器根据.proto 自动成.java 文件在使用 Netty 开发时,经常会结合 Protobuf 作为 codec (编解码器)去使用,具体用法如下所示。
使用步骤:

  1. 第一步:将传递数据的实体类生成【基于构建者模式设计】
  2. 第二步:配置编解码器
  3. 第三步:传递数据使用生成后的实体类

使用案例

1 引入依赖

<dependency><groupId>com.google.protobuf</groupId><artifactId>protobuf-java</artifactId><version>3.21.11</version>
</dependency>

定义protoc文件,是生成具体类的描述:
语法规则:https://www.topgoer.com/%E5%BE%AE%E6%9C%8D%E5%8A%A1/Protobuf%E8%AF%AD%E6%B3%95.html

syntax = "proto3";
option java_outer_classname = "BookMessageDB";
message Book{
int32 id = 1;
string name = 2;
}

2 安装插件
在这里插入图片描述
GenProtobuf是生产插件。Protobuf是一定要安装的。
配置GenProtobuf:
在这里插入图片描述
做如下配置:
在这里插入图片描述

特别注意:这个版本要和你引入的依赖版本一致,否则会出先有些方法或类找不到报红的情况
在这里插入图片描述

public class AIOServer {public static void main(String[] args) throws InterruptedException {EventLoopGroup bossGroup = new NioEventLoopGroup();EventLoopGroup workGroup = new NioEventLoopGroup();ServerBootstrap b = new ServerBootstrap();b.group(bossGroup, workGroup).channel(NioServerSocketChannel.class).option(ChannelOption.SO_BACKLOG, 128).childOption(ChannelOption.SO_KEEPALIVE, true).childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {// 解码ch.pipeline().addLast("decoder", new ProtobufDecoder(BookMessage.Book.getDefaultInstance()));ch.pipeline().addLast(new NettyServerHandler());}});System.out.println("============服务器启动");b.bind(9999).sync();//        bossGroup.shutdownGracefully();
//        workGroup.shutdownGracefully();}
}
public class AIOClient {public static void main(String[] args) throws InterruptedException {NioEventLoopGroup group = new NioEventLoopGroup();Bootstrap bootstrap = new Bootstrap();bootstrap.group(group).channel(NioSocketChannel.class).handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel ch) throws Exception {// 设置编码器ch.pipeline().addLast("encoder", new ProtobufEncoder());ch.pipeline().addLast(new NettyClientHandler());}});System.out.println();ChannelFuture connect = bootstrap.connect(new InetSocketAddress(9999));connect.channel().closeFuture().sync();}
}
public class NettyClientHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {ByteBuf buf=(ByteBuf) msg;System.out.println("client msg:"+buf.toString(CharsetUtil.UTF_8));}@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {BookMessage.Book book =BookMessage.Book.newBuilder().setId(1).setName("beyound").build();ctx.writeAndFlush(book);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {ctx.close();}
}
public class NettyServerHandler extends ChannelInboundHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {BookMessage.Book book=(BookMessage.Book)msg;System.out.println("receive book msg:"+ book.getName());}@Overridepublic void channelReadComplete(ChannelHandlerContext ctx) throws Exception {ctx.writeAndFlush(Unpooled.copiedBuffer("response", Charset.defaultCharset()));}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {ctx.close();}
}

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

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

相关文章

公共字段自动填充

在开发中经常面临对于一些公共字段的赋值。 如在下表中&#xff1a; 如何让程序自动为我们需要赋值的公共字段进行赋值&#xff0c;避免在业务代码中重复写这些公共字段的赋值代码 如下图所示&#xff1a; 实现思路&#xff1a; 1.自定义注解AutoFill&#xff0c;用于标识需…

linux环境安装cuda toolkit

1 全新安装 如果环境中没安装过cuda版本&#xff0c; 这种情况下比较简单。 直接在https://developer.nvidia.com/cuda-toolkit-archive选择对应版本下载安装即可。 如下为安装cuda toolkit 11.8. 2 环境中已经存在其他版本 这种情况下比较复杂一些。 首先要确认最高支持的…

李沐动手学习深度学习——4.2练习

1. 在所有其他参数保持不变的情况下&#xff0c;更改超参数num_hiddens的值&#xff0c;并查看此超参数的变化对结果有何影响。确定此超参数的最佳值。 通过改变隐藏层的数量&#xff0c;导致就是函数拟合复杂度下降&#xff0c;隐藏层过多可能导致过拟合&#xff0c;而过少导…

【MySQL】表的内连和外连(重点)

表的连接分为内连和外连。 一、内连接 内连接实际上就是利用 where 子句对两种表形成的笛卡儿积进行筛选&#xff0c;前面学习的查询都是内连接&#xff0c;也是在开发过程中使用的最多的连接查询。 select 字段 from 表1 inner join 表2 on 连接条件 and 其他条件; 注意&…

Linux使用基础命令

1.常用系统工作命令 (1).用echo命令查看SHELL变量的值 qiangziqiangzi-virtual-machine:~$ echo $SHELL /bin/bash(2).查看本机主机名 qiangziqiangzi-virtual-machine:~$ echo $HOSTNAME qiangzi-virtual-machine (3).date命令用于显示/设置系统的时间或日期 qiangziqian…

Linux多线程服务端编程:使用muduo C++网络库 学习笔记 附录B 从《C++ Primer(第4版)》入手学习C++

这是作者为《C Primer&#xff08;第4版&#xff09;&#xff08;评注版&#xff09;》写的序言&#xff0c;文中“本书”指的是这本书评注版。 B.1 为什么要学习C 2009年本书作者Stanley Lippman先生应邀来华参加上海祝成科技举办的C技术大会&#xff0c;他表示人们现在还用…

扩展学习|大数据分析的现状和分类

文献来源&#xff1a;[1] Mohamed A , Najafabadi M K , Wah Y B ,et al.The state of the art and taxonomy of big data analytics: view from new big data framework[J].Artificial Intelligence Review: An International Science and Engineering Journal, 2020(2):53. 下…

蓝桥杯(3.2)

1209. 带分数 import java.io.*;public class Main {static BufferedReader br new BufferedReader(new InputStreamReader(System.in));static PrintWriter pw new PrintWriter(new OutputStreamWriter(System.out));static final int N 10;static int n, cnt;static int[…

LabVIEW流量控制系统

LabVIEW流量控制系统 为响应水下航行体操纵舵翼环量控制技术的试验研究需求&#xff0c;通过LabVIEW开发了一套小量程流量控制系统。该系统能够满足特定流量控制范围及精度要求&#xff0c;展现了其在实验研究中的经济性、可靠性和实用性&#xff0c;具有良好的推广价值。 项…

tritonserver学习之八:redis_caches实践

tritonserver学习之一&#xff1a;triton使用流程 tritonserver学习之二&#xff1a;tritonserver编译 tritonserver学习之三&#xff1a;tritonserver运行流程 tritonserver学习之四&#xff1a;命令行解析 tritonserver学习之五&#xff1a;backend实现机制 tritonserv…

【C++初阶】内存管理

目录 一.C语言中的动态内存管理方式 二.C中的内存管理方式 1.new/delete操作内置类型 2.new和delete操作自定义类型 3.浅识抛异常 &#xff08;内存申请失败&#xff09; 4.new和delete操作自定义类型 三.new和delete的实现原理 1.内置类型 2.自定义类型 一.C语…

C++学习笔记:二叉搜索树

二叉搜索树 什么是二叉搜索树?搜索二叉树的操作查找插入删除 二叉搜索树的应用二叉搜索树的代码实现K模型:KV模型 二叉搜索树的性能怎么样? 什么是二叉搜索树? 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树: 若它的左子树…

Linux安装Nginx详细步骤

1、创建两台虚拟机&#xff0c;分别为主机和从机&#xff0c;区别两台虚拟机的IP地址 2、将Nginx素材内容上传到/usr/local目录&#xff08;pcre,zlib,openssl,nginx&#xff09; 附件 3、安装pcre库   3.1 cd到/usr/local目录 3.2 tar -zxvf pcre-8.36.tar.gz 解压 3.3 cd…

MATLAB图像噪声添加与滤波

在 MATLAB 中添加图像噪声和进行滤波通常使用以下函数&#xff1a; 添加噪声&#xff1a;可以使用imnoise函数向图像添加各种类型的噪声&#xff0c;如高斯噪声、椒盐噪声等。 滤波&#xff1a;可以使用各种滤波器对图像进行滤波处理&#xff0c;例如中值滤波、高斯滤波等。 …

前端学习、HTML

html是由一些标签构成的&#xff0c;标签之间可以嵌套&#xff0c;每个标签都有开始标签和结束标签&#xff0c;也有部分标签只有开始标签&#xff0c;没有结束标签。html的标签也可以成为元素。&#xff08;树形结构&#xff09; html文件的最顶层标签就是html。 head用来放…

**蓝桥OJ 178全球变暖 DFS

蓝桥OJ 178全球变暖 思路: 将每一座岛屿用一个颜色scc代替, 用dx[]和dy[]判断他的上下左右是否需要标记颜色,如果已经标记过颜色或者是海洋就跳过.后面的淹没,实际上就是哪个块上下左右有陆地,那么就不会被淹没,我用一个tag标记,如果上下左右一旦有海洋,tag就变为false.如果tag…

用冒泡排序模拟C语言中的内置快排函数qsort!

目录 ​编辑 1.回调函数的介绍 2. 回调函数实现转移表 3. 冒泡排序的实现 4. qsort的介绍和使用 5. qsort的模拟实现 6. 完结散花 悟已往之不谏&#xff0c;知来者犹可追 创作不易&#xff0c;宝子们&#xff01;如果这篇文章对你们有帮助的话&#xff0c;别忘了给个免…

机器学习:模型评估和模型保存

一、模型评估 from sklearn.metrics import accuracy_score, confusion_matrix, classification_report# 使用测试集进行预测 y_pred model.predict(X_test)# 计算准确率 accuracy accuracy_score(y_test, y_pred) print(f"Accuracy: {accuracy*100:.2f}%")# 打印…

整数和浮点数在内存中的存储(大小端字节序,浮点数的存取)

目录 1.整数在内存中的存储 2.大小端字节序和字节序判断 2.1什么是大小端&#xff1f; 2.2为什么会有大小端 3.浮点数在内存中的存储 3.1浮点数的存储 3.1.1 浮点数存的过程 3.1.2 浮点数取的过程 3.2 解析 3.3 验证浮点数的存储方式 1.整数在内存中的存储 整数的二进…

亿道信息轻工业三防EM-T195,零售、制造、仓储一网打尽

厚度仅10.5mm&#xff0c;重量仅0.65千克的EM-T195&#xff0c;其紧凑而纤薄的设计为以往加固型平板带来了全新的轻薄概念。尽管设计时尚、轻薄&#xff0c;但经过军用认证的强固性仍然能够承受所有具有挑战性的环境条件。随身携带无负担的轻便性加上抗震功能使其成为餐厅、酒店…