`

MessagePack, Protocol Buffers和Thrift序列化框架原理和比较说明

    博客分类:
  • PHP
阅读更多

http://jimmee.iteye.com/blog/2042420

第1部分 messagepack说明

1.1messagepack的消息编码说明

为什么messagepackjson序列化使用的字节流更少, 可通过图1-1、图1-2有个直观的感觉。

 

 

1- 1 messagepackjson的格式对比1



 

1- 2 messagepackjson的格式对比2

messagepack的具体的消息格式如图1-3所示,messagepack的数据类型主要分类两类:固定长度类型和可变长度类型。



 

1- 3 messagepack的消息格式

messagepack的具体类型信息表示如图1-4所示。

 

 

1- 4 messagepack的类型信息

1.2 messagepack的序列化和反序列化方式

现在msgpack能支持基本的数据类型,支持listmap, 还支持自定义的数据类型。例子1, 序列化和反序列化一个javabean, 只要加上@MessagePackMessage的注解。

 

Java代码 复制代码 收藏代码
  1. /** 
  2.  * 一个用于messagepack测试序列化和反序列的javabean 
  3.  *  
  4.  * @author jimmee 
  5.  */  
  6. @MessagePackMessage   
  7. public class Person {  
  8. /** 编号 */  
  9. public int id;  
  10. /** 名字 */  
  11. public String name;  
  12. /**身高*/  
  13. public double height;  
  14. /** 
  15.  * 默认构造函数 
  16.  */  
  17. public Person() {  
  18. }  
/**
 * 一个用于messagepack测试序列化和反序列的javabean
 * 
 * @author jimmee
 */
@MessagePackMessage 
public class Person {
/** 编号 */
public int id;
/** 名字 */
public String name;
/**身高*/
public double height;
/**
 * 默认构造函数
 */
public Person() {
}

 

 

 

序列化直接调用MessagePackpack方法;反序列化则调用对应的unpack方法。这两个方法,都支持传递序列化和反序列化的数据类型。

1.3 与json的序列化性能对比

如下所示,通过100条数据的序列化和反序列化进行对比。

 

Java代码 复制代码 收藏代码
  1. List<Map> msgs = new ArrayList<Map>();  
  2. for (int i = 0; i < 100; i++) {  
  3. Map msg = new HashMap();  
  4. msg.put(Const.FID, i);  
  5. msg.put(Const.SUBJECT, "subject" + i);  
  6. msg.put(Const.LABEL0, 1);  
  7. msg.put(Const.FROM, "test@163.com");  
  8. msg.put(Const.TO, "test@126.com");  
  9. msg.put(Const.MODIFIED_DATE, new Date().getTime());  
  10. msg.put(Const.RECEIVED_DATE, new Date().getTime());  
  11. msg.put(Const.SENT_DATE, new Date().getTime());  
  12. msgs.add(msg);  
  13.     }  
List<Map> msgs = new ArrayList<Map>();
for (int i = 0; i < 100; i++) {
Map msg = new HashMap();
msg.put(Const.FID, i);
msg.put(Const.SUBJECT, "subject" + i);
msg.put(Const.LABEL0, 1);
msg.put(Const.FROM, "test@163.com");
msg.put(Const.TO, "test@126.com");
msg.put(Const.MODIFIED_DATE, new Date().getTime());
msg.put(Const.RECEIVED_DATE, new Date().getTime());
msg.put(Const.SENT_DATE, new Date().getTime());
msgs.add(msg);
    }

 

 

比较结果如表1-1所示。

1- 1 messagepackjson的性能对比

框架

字节大小(byte

序列化时间(ns

反序列化时间(ns

messagepack

12793

2313335

529458

json

17181

 1338371

1776519

 

可以看出,messagepack的序列化字节数比json小将近30%;序列化时间messagepack差不多是json的两倍;反序列化时间,messagepack只需要json30%的时间。

但是,值得注意的是,虽然messagepack的反序列化时间比较少,但是要真正转换为前端需要的类型参数格式,还需要额外的一些时间。

第2部分 protocol buffers

2.1 protocol buffers的消息编码说明

Protocol Buffers支持的数据类型如下图所示:



  

2- 1 protocol buffers支持的数据类型。

首先对Varint进行说明。Varint 是一种紧凑的表示数字的方法。它用一个或多个字节来示一个数字,值越小的数字使用越少的字节数。这能减少用来表示数字的字节数。

比如对于 int32 类型的数字,一般需要 个 byte 来表示。但是采用 Varint,对于很小的 int32 类型的数字,则可以用 个 byte 来表示。当然,采用 Varint 表示法,大的数字则需要 个 byte 来表示。从统计的角度来说,一般不会所有的消息中的数字都是大数,因此大多数情况下,采用 Varint 后,可以用更少的字节数来表示数字信息。

Varint 中的每个 byte 的最高位 bit 有特殊的含义,如果该位为 1,表示后续的 byte 也是该数字的一部分,如果该位为 0,则结束。其他的 个 bit 都用来表示数字。因此小于 128 的数字都可以用一个 byte 表示。大于 128 的数字,比如 300,会用两个字节来表示:1010 1100 0000 0010

2-2说明了 Google Protocol Buffer 如何解析两个 bytes。注意到最终计算前将两个 byte 的位置相互交换过一次,这是因为 Google Protocol Buffer 字节序采用 little-endian 的方式。



  

2- 2 protocol buffers解析两个字节

消息经过序列化后会成为一个二进制数据流,该流中的数据为一系列的 Key-Value 对,如图2-3所示。



  

2- 3 protocol buffers的消息流

采用这种 Key-Pair 结构无需使用分隔符来分割不同的 Field。对于可选的 Field,如果消息中不存在该 field,那么在最终的 Message Buffer 中就没有该 field,这些特性都有助于节约消息本身的大小。

假设我们生成如下的一个消息Message

 Message.id = 5

 Message.info = “hello”

则最终的 Message Buffer 中有两个 Key-Value 对,一个对应消息中的 id;另一个对应 info

Key 用来标识具体的 field,在解包的时候,Protocol Buffer 根据 Key 就可以知道相应的 Value 应该对应于消息中的哪一个 field

Key 的定义如下:

 (field_number << 3) | wire_type 

可以看到 Key 由两部分组成。第一部分是 field_number。第二部分为 wire_type。表示 Value 的传输类型。

wire type如表2-1所示。

2- 1 wire type说明

Type 

Meaning 

Used For 

Varint 

int32, int64, uint32, uint64, sint32, sint64, bool, enum 

64-bit 

fixed64, sfixed64, double 

Length-delimited 

string, bytes, embedded messages, packed repeated fields 

Start group 

Groups (deprecated) 

End group 

Groups (deprecated) 

32-bit 

fixed32, sfixed32, float 

 

在计算机内,一个负数一般会被表示为一个很大的整数,因为计算机定义负数的符号位为数字的最高位。如果采用 Varint 表示一个负数,那么一定需要 个 byte。为此 Google Protocol Buffer 定义了 sint32sint64 类型,采用 zigzag 编码。

Zigzag 编码用无符号数来表示有符号数字,正数和负数交错,如图2-3所示。使用 zigzag 编码,绝对值小的数字,无论正负都可以采用较少的 byte 来表示,充分利用了 Varint 这种技术。


  

2- 4 ZigZag编码

2.2 protocol buffers的序列化和反序列化

步骤:

创建消息的定义文件.proto

使用protoc工具将proto文件转换为相应语言的源码;

使用类库支持的序列化和反序列化方法进行操作。

 

以同样的数据的操作为例:

1. 定义proto文件messages.ptoto

 

Java代码 复制代码 收藏代码
  1. message MessageMeta {  
  2.   required int32 id = 1;  
  3.   required string subject = 2;    
  4. optional int32 lablel0 = 3;  
  5. required string from = 4;  
  6. required string to = 5;  
  7. optional int64 modifiedDate = 6;  
  8. optional int64 receivedDate = 7;  
  9. optional int64 sentDate = 8;  
  10. }  
message MessageMeta {
  required int32 id = 1;
  required string subject = 2;  
optional int32 lablel0 = 3;
required string from = 4;
required string to = 5;
optional int64 modifiedDate = 6;
optional int64 receivedDate = 7;
optional int64 sentDate = 8;
}

 

 

 

 

Java代码 复制代码 收藏代码
  1. message MessageMetas {  
  2. repeated MessageMeta msg = 1;  
  3. }  
message MessageMetas {
repeated MessageMeta msg = 1;
}

 

 

2. message.proto文件转换为java语言的源码

例如, 执行命令:protoc -I=src --java_out=out src/messages.proto产生Messagesjava文件。

3. 执行序列化和反序列化

 

Java代码 复制代码 收藏代码
  1. MessageMetas.Builder msgsBuilder = MessageMetas.newBuilder();  
  2. for (int i = 0; i < 100; i++) {  
  3. MessageMeta.Builder msgBuilder = MessageMeta.newBuilder();  
  4. msgBuilder.setId(i);  
  5. msgBuilder.setSubject("subject" + i);  
  6. msgBuilder.setLablel0(1);  
  7. msgBuilder.setFrom("test@163.com");  
  8. msgBuilder.setTo("test@126.com");  
  9. msgBuilder.setModifiedDate(new Date().getTime());  
  10. msgBuilder.setReceivedDate(new Date().getTime());  
  11. msgBuilder.setSentDate(new Date().getTime());  
  12. msgsBuilder.addMsg(msgBuilder.build());  
  13. }  
  14. MessageMetas msgs = msgsBuilder.build();  
MessageMetas.Builder msgsBuilder = MessageMetas.newBuilder();
for (int i = 0; i < 100; i++) {
MessageMeta.Builder msgBuilder = MessageMeta.newBuilder();
msgBuilder.setId(i);
msgBuilder.setSubject("subject" + i);
msgBuilder.setLablel0(1);
msgBuilder.setFrom("test@163.com");
msgBuilder.setTo("test@126.com");
msgBuilder.setModifiedDate(new Date().getTime());
msgBuilder.setReceivedDate(new Date().getTime());
msgBuilder.setSentDate(new Date().getTime());
msgsBuilder.addMsg(msgBuilder.build());
}
MessageMetas msgs = msgsBuilder.build();

 

 

之后调用相应的writeTo方法进行序列化, 调用parseFrom进行反序列化。

2.3 与json等的性能对比

2- 2 性能对比表格

框架

字节大小(byte

序列化时间(ns

反序列化时间(ns

messagepack

12793

2313335

529458

protocol buffers

6590

941790

408571

json

17181

 1338371

1776519

 

可以看出,protocol buffers在字节流,序列化时间和反序列化时间方面都明显较优(即空间和时间上都比较好)。

第3部分 thrift

thrift的架构如图3-1所示。图3-1显示了创建serverclientstack。最上面的是IDL,然后生成ClientProcessor。红色的是发送的数据。protocoltransport Thrift运行库的一部分。通过Thrift 你只需要关心服务的定义,而不需要关心protocoltransport

Thrift支持 text 和 binary protocolsbinary protocols要比text protocols,但是有时候 text protocols比较有用(例如:调试的时候)。支持的协议有:

TBinaryProtocol 直接的二进制格式

TCompactProtocol 效率和高压缩编码数据

TDenseProtocoal  和TCompactProtocol相似,但是省略了meta信息,从哪里发送的,增加了receiver。还在实验中,java实现还不可用。

TJSONProtocoal使用JSON

TSImpleJSONProtocoal 只写的protocol使用JSON。适合被脚本语言转化

TDebugProtocoal使用人类可读的text 格式 帮助调试



  

3- 1 thrift架构图

上面的protocol 说明了传送的是什么样的数据Thrift transports 则说明了怎样传送这些数据。支持的transport

TSocket 使用 blocking socket I/O

TFramedTransport 以帧的形式发送,每帧前面是一个长度。要求服务器来non-blocking server

TFileTransport 写到文件

TMemoryTransport 使用内存 I/O java实现中在内部使用了ByteArrayOutputStream

TZlibTransport 压缩 使用zlibjava实现中还不可用

最后,thrift 提供了servers

TSimpleServer 单线程server,使用标准的blocking IO用于测试

TThreadPoolServer多线程server 使用标准的blocking IO

TNonblockingServer  多线程 server使用 non-blocking IO java实现中使用了NIO channels),TFramedTransport必须使用在这个服务器。

一个server只允许定义一个接口服务。这样的话多个接口需要多个server。这样会带来资源的浪费。通常可以通过定义一个组合服务来解决。

3.1 thrift的消息编码说明

1. 支持的数据类型

所有编程语言中都可用的关键类型。

bool 布尔值,真或假

byte 有符号字节

i16  16位有符号整数

i32  32位有符号整数

i64  64位有符号整数

double 64位浮点数

string 与编码无关的文本或二进制字符串

可基于基本类型定义结构体,例如:

 

Java代码 复制代码 收藏代码
  1. struct Example {  
  2. 1:i32 number=10,  
  3. 2:i64 bigNumber,  
  4. 3:double decimals,  
  5. 4:string name="thrifty"  
  6. }  
struct Example {
1:i32 number=10,
2:i64 bigNumber,
3:double decimals,
4:string name="thrifty"
}

 

 

支持的容器有list<type>set<type>Map<type1,type2>

若使用TCompactProtocol,传递的消息形式如图3-2所示:

 

 

3- 2 thriftcompact方式的消息流

在这种方式下,对整数而言,也是采用可变长度的方式进行实现。一个字节,最高位表示是否还有数据,低7位是实际的数据,如图3-3所示, 整数106903的编码, 相比普通的int类型,节省一个字节。



  

3- 3 compact方式对一个整数106903进行编码

3.2thrift的序列化和反序列化方式

步骤:

创建thrift接口定义文件;

thrift的定义文件转换为对应语言的源代码;

选择相应的protocol,进行序列化和反序列化。

仍以同样的数据对象为例子:

定义thrift文件messages.thrift

 

Java代码 复制代码 收藏代码
  1. struct MessageMeta {  
  2.   1:i32 id;  
  3.   2:string subject;    
  4. 3:i32 lablel0;  
  5. 4:string from;  
  6. 5:string to;  
  7. 6:i64 modifiedDate;  
  8. 7:i64 receivedDate;  
  9. 8:i64 sentDate;  
  10. }  
  11.    
  12. struct MessageMetas {  
  13. 1:list<MessageMeta> msgs;  
  14. }  
struct MessageMeta {
  1:i32 id;
  2:string subject;  
3:i32 lablel0;
4:string from;
5:string to;
6:i64 modifiedDate;
7:i64 receivedDate;
8:i64 sentDate;
}
 
struct MessageMetas {
1:list<MessageMeta> msgs;
}

 

 

 

2. 将定义的文件转换成相应的java源码

执行命令:thrift -gen java messages.thrift

3. 执行序列化和反序列化

 

Java代码 复制代码 收藏代码
  1. MessageMetas msgs = new MessageMetas();  
  2. List<MessageMeta> msgList = new ArrayList<MessageMeta>();  
  3. for (int i = 0; i < 100; i++) {  
  4. MessageMeta msg = new MessageMeta();  
  5. msg.setId(i);  
  6. msg.setSubject("subject" + i);  
  7. msg.setLablel0(1);  
  8. msg.setFrom("test@163.com");  
  9. msg.setTo("test@126.com");  
  10. msg.setModifiedDate(new Date().getTime());  
  11. msg.setReceivedDate(new Date().getTime());  
  12. msg.setSentDate(new Date().getTime());  
  13. msgList.add(msg);  
  14. }  
  15. msgs.setMsgs(msgList);  
  16. // 序列化  
  17. ByteArrayOutputStream out = new ByteArrayOutputStream();  
  18. TTransport trans = new TIOStreamTransport(out);  
  19. TBinaryProtocol tp = new TBinaryProtocol(trans);  
  20. msgs.write(tp);  
  21.    
  22. byte [] buf = out.toByteArray();  
  23. // 反序列化  
  24. ByteArrayInputStream in = new ByteArrayInputStream(buf);  
  25. trans = new TIOStreamTransport(in);  
  26. tp = new TBinaryProtocol(trans);  
  27. MessageMetas msgs2 = new MessageMetas();  
  28. msgs2.read(tp);  
MessageMetas msgs = new MessageMetas();
List<MessageMeta> msgList = new ArrayList<MessageMeta>();
for (int i = 0; i < 100; i++) {
MessageMeta msg = new MessageMeta();
msg.setId(i);
msg.setSubject("subject" + i);
msg.setLablel0(1);
msg.setFrom("test@163.com");
msg.setTo("test@126.com");
msg.setModifiedDate(new Date().getTime());
msg.setReceivedDate(new Date().getTime());
msg.setSentDate(new Date().getTime());
msgList.add(msg);
}
msgs.setMsgs(msgList);
// 序列化
ByteArrayOutputStream out = new ByteArrayOutputStream();
TTransport trans = new TIOStreamTransport(out);
TBinaryProtocol tp = new TBinaryProtocol(trans);
msgs.write(tp);
 
byte [] buf = out.toByteArray();
// 反序列化
ByteArrayInputStream in = new ByteArrayInputStream(buf);
trans = new TIOStreamTransport(in);
tp = new TBinaryProtocol(trans);
MessageMetas msgs2 = new MessageMetas();
msgs2.read(tp);

 

 

3.3json等的性能对比

3- 1 性能对比

框架

字节大小(byte

序列化时间(ns

反序列化时间(ns

messagepack

12793

2313335

529458

protocol buffers

6590

941790

408571

thrift

6530

798696

754458

json

17181

 1338371

1776519

 

通过对比,可以发现thrift总的来说,都比较不错。

第4部分 小结

通过对messagepackprotocol buffers以及thrift的分析,主要分析了这些框架的序列化和反序列化部分的内容。实际上messagepackthrift都还有自己的rpc调用框架。

所有的测试都是在本机上进行,基于100条元数据进行测试。可能不同数据,以及不同的规模,测试结果应该会存在差别,https://github.com/eishay/jvm-serializers/wiki/的有比较好的测试结果说明。根据自己的测试,从性能上说,messagepackprotocol buffers以及thrift都比json好(在测试时,发现messagepack序列化的时间稍微多一些)。

从编程语言上来说,messagepackprotocol buffers以及thrift,当然还包括json,都是支持跨语言的通讯的。

从接口定义的灵活性来(或者是否支持动态类型),messagepackprotocol buffers以及thrift较好,后两者都要预先定义schema并相对固定

 

 实际工作中, 一般都采用protocol buffers或者thrift.

 

第5部分 参考资料

1. http://msgpack.org/

2. http://code.google.com/intl/zh-CN/apis/protocolbuffers/docs/overview.html

3. http://jnb.ociweb.com/jnb/jnbJun2009.html

4. http://code.google.com/p/thrift-protobuf-compare/

5. http://www.tbdata.org/archives/1307

6. https://github.com/eishay/jvm-serializers/wiki/

7. http://wiki.apache.org/thrift/

8. http://pypi.python.org/pypi/msgpack-python/

分享到:
评论

相关推荐

    平:有原则且有效的二进制序列化

    5. **Apache Thrift**:另一种跨语言的序列化框架,它不仅提供序列化,还提供了服务接口定义和RPC框架。 6. **MessagePack**:轻量级的二进制序列化格式,比JSON更快更小,适合嵌入式设备和实时系统。 7. **设计...

    cpp-serializers:比较各种C ++数据序列化库(节俭,protobuf等)的基准

    1. **Google Protocol Buffers (protobuf)**:protobuf是Google开发的一种高效的数据序列化协议,支持C++、Java和Python等多种语言。它提供了强大的代码生成工具,可以将定义的.proto文件转换为结构化数据的存取代码...

    20170723-课堂笔记1

    在Java之外,还有许多其他序列化技术,如JSON、Hessian、XML、protobuf、kryo、MsgPack、FST、thrift和protostuff等,每种技术都有其独特的优点和适用场景。例如,protobuf提供了高效、紧凑的二进制编码,kryo提供了...

    c++开源库大全21

    - **MessagePack**:提供JSON类似的二进制序列化库,适合高效数据交换。 - **protobuf (Protocol Buffers)**:Google的数据交换格式,支持C++和其他多种语言。 - **protobuf-c**:C语言的Protocol Buffers实现。 ...

    vue3 访问通义千问聊天代码例子

    vue3 访问通义千问聊天代码例子

    基于Python的Flask-vue基于Hadoop的智慧校园数据共享平台实现源码-演示视频.zip

    基于Python的Flask-vue基于Hadoop的智慧校园数据共享平台实现源码-演示视频 项目关键技术 开发工具:Pycharm 编程语言: python 数据库: MySQL5.7+ 后端技术:Flask 前端技术:HTML 关键技术:HTML、MYSQL、Python 数据库工具:Navicat、SQLyog

    C#调用Ni板卡进行实现采集任务(模拟量输入输出)示例1

    【实验1】:读取一次AI0通道数值 【实验2】:一次读取AI0通道多个数值 【实验3】:单次模拟量输出 【实验4】:连续模拟量输出(输出一个正弦曲线)

    无人船的Smith-PID跟踪控制方法研究及实现:融合传统与最优PID策略的LOS曲线跟踪资料,基于无人船Smith-PID改进

    无人船的Smith-PID跟踪控制方法研究及实现:融合传统与最优PID策略的LOS曲线跟踪资料,基于无人船Smith-PID改进跟踪控制技术及其LOS曲线跟踪方法研究资料,基于无人船的smith-pid跟踪控制资料。 首先,针对pid进行了改进,有传统pid,最优pid和基于smith的pid三种控制方式。 然后还在smithpid基础上设计了LOS的曲线跟踪方法。 (有对应参考文献)。 有意者可直接联系,参考学习资料。 python语言。 ,基于无人船的Smith-PID跟踪控制; PID改进(传统PID、最优PID、基于Smith的PID); Smith-PID曲线跟踪方法; 参考学习资料; Python语言。,基于无人船的Smith-PID优化跟踪控制资料

    自研船舶电力推进系统MATLAB仿真报告:从柴油机+同步发电机到异步电机直接转矩控制的全面模拟与实践,船舶电力推进系统自搭MATLAB仿真报告:从柴油机同步发电机到异步电机直接转矩控制的完整过程与参

    自研船舶电力推进系统MATLAB仿真报告:从柴油机+同步发电机到异步电机直接转矩控制的全面模拟与实践,《船舶电力推进系统自搭MATLAB仿真报告:从柴油机同步发电机到异步电机直接转矩控制的完整过程与参数配置详解》,自己搭建的船舶电力推进系统(船舶电力推进自动控制)完全自搭MATLAB仿真,可适度,含对应27页正文的中文报告,稀缺资源,仿真包括船舶电站,变流系统和异步电机直接转矩控制,放心用吧。 三个文件逐层递进 柴油机+同步发电机(船舶电站) 柴油机+同步发电机+不控整流全桥逆变 柴油机+同步发电机+变流模块+异步电机直接转矩控制 所有参数都是配好的,最大负载参考变流系统所带负载两倍,再大柴油机和同步发电机参数就不匹配了,有能力可以自己调 ,核心关键词:船舶电力推进系统; MATLAB仿真; 船舶电站; 变流系统; 异步电机直接转矩控制; 柴油机; 同步发电机; 不控整流全桥逆变; 参数配比。,《船舶电力推进系统MATLAB仿真报告》

    西门子博图WinCC V15自动化系统项目实战:多服务器客户端下的PID DCS闭环控制及参数调整实战指南,西门子博图WinCC V15自动化系统项目实战:多服务器客户端下的PID DCS闭环控制及参

    西门子博图WinCC V15自动化系统项目实战:多服务器客户端下的PID DCS闭环控制及参数调整实战指南,西门子博图WinCC V15自动化系统项目实战:多服务器客户端下的PID DCS闭环控制及参数调整实战指南,西门子博图WinCC V 15大型自动化系统项目,包含多台服务器客户端项目,系统采用安全1516F -3PN DP 外挂多台精智面板,1200PLC ET200SP 变频器 对整个工艺过程PID DCS 闭环过程控制,如何调整温度压力流量液位等参数,实用工程项目案例 ,西门子博图WinCC V 15; 大型自动化系统; 多台服务器客户端; 安全外挂; 精智面板; 1200PLC ET200SP; 变频器; PID DCS; 闭环过程控制; 温度压力流量液位调整; 工程项目案例,西门子博图WinCC V15大型项目:多服务器客户端的PID DCS闭环控制与实用参数调整

    计算机网络资源全解析: 硬件、软件、协议及安全机制详解与应用

    内容概要:本文详尽介绍了计算机网络相关资源及其各方面构成要素,首先阐述了硬件层面的各种传输媒介和设备如双绞线、同轴电缆、光纤以及台式电脑、笔记本、大型计算机等设备,还包括网络互联所需的各类组件如网卡、交换机、路由器等。其次探讨了多种操作系统的特性和主要功能,以及各类通讯和支持应用程序的概述,涵盖浏览器、图像和视频编辑等常用软件。再深入讨论了多种常见网络协议如TCP、UDP、HTTP等的功能特性。最后还提到了确保网络安全运行的重要措施和工具如MIB、SNMP以及防火墙、入侵检测系统等。并且简要提到计算机网络在不同的应用环境,从局域网到移动网络。 适合人群:所有对计算机网络技术感兴趣的初学者和希望深入了解各个组成成分的技术人员. 使用场景及目标:为用户提供计算机网络资源全面而系统的认识,帮助他们建立对于该领域的理论和技术的扎实认知基础,提高在实际环境中识别配置及维护计算机网络系统的能力.

    【GPS北斗定位】基于matlab卡尔曼滤波KF北斗GPS单模和双模定位比较【含Matlab源码 10974期】.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    ABAQUS中隧道结构模型的无限元应用:超声激励源的施加方法、3D无限元吸收边界的添加技巧、模型结果精确性校核流程及教学视频与CAE、INP文件解析,ABAQUS隧道模型中3D无限元吸收边界的应用:超

    ABAQUS中隧道结构模型的无限元应用:超声激励源的施加方法、3D无限元吸收边界的添加技巧、模型结果精确性校核流程及教学视频与CAE、INP文件解析,ABAQUS隧道模型中3D无限元吸收边界的应用:超声激励源的施加与模型结果精确性校核的实践教程,ABAQUS无限元吸收边界,abaqus隧道无限元,1.超声激励源施加;2.3D无限元吸收边界添加方法;3.模型结果精确性校核;4.提供教学视频,cae、inp文件。 ,ABAQUS无限元吸收边界;ABAQUS隧道无限元;超声激励源施加;3D无限元吸收边界添加;模型结果精确性校核;CAE和INP文件。,ABAQUS中超声激励下无限元吸收边界设置及模型精度验证教程

    【SLAM】基于matlab扩展卡尔曼滤波器EKF同步定位与建图SLAM【含Matlab源码 10978期】复现.mp4

    海神之光上传的视频是由对应的完整代码运行得来的,完整代码皆可运行,亲测可用,适合小白; 1、从视频里可见完整代码的内容 主函数:main.m; 调用函数:其他m文件;无需运行 运行结果效果图; 2、代码运行版本 Matlab 2019b;若运行有误,根据提示修改;若不会,私信博主; 3、运行操作步骤 步骤一:将所有文件放到Matlab的当前文件夹中; 步骤二:双击打开main.m文件; 步骤三:点击运行,等程序运行完得到结果; 4、仿真咨询 如需其他服务,可私信博主; 4.1 博客或资源的完整代码提供 4.2 期刊或参考文献复现 4.3 Matlab程序定制 4.4 科研合作

    git自用lllllllllllllllllll

    git自用lllllllllllllllllll

    【Django小白项目】参照本,包含python、HTML、Django

    本资源与文章【Django小白项目】为一体,此为已成功项目,供给给Django初学者做参考,有不会的问题可以私信我噢~

    C++矩阵运算库matrix

    使用一维数据表示向量和二维矩阵,支持常用运算。

    基于STM32的宠物自动喂食器系统设计.pdf

    1、以上文章可用于参考,请勿直接抄袭,学习、当作参考文献可以,主张借鉴学习 2、资源本身不含 对应项目代码,如需完整项目源码,请私信博主获取

    基于多目标粒子群优化算法(MOPSO)的微电网多目标经济运行分析与优化策略考虑响应侧响应的协同调度策略,基于多目标粒子群优化算法(MOPSO)的微电网经济调度优化:含风光储荷一体化模型与需求侧响应策略

    基于多目标粒子群优化算法(MOPSO)的微电网多目标经济运行分析与优化策略考虑响应侧响应的协同调度策略,基于多目标粒子群优化算法(MOPSO)的微电网经济调度优化:含风光储荷一体化模型与需求侧响应策略,考虑需求侧响应的微电网多目标经济运行 建立了含风光储荷的微电网模型,以发电侧成本(包括风光储以及电网的购电成本)和负荷侧成本最小为目标,考虑功率平衡以及储能SOC约束,建立了多目标优化模型,通过分时电价引导负荷需求侧响应,得到可削减负荷量,同时求解模型,得到风光储以及电网的运行计划。 这段代码是一个使用多目标粒子群优化算法(MOPSO)解决问题的程序。下面我将对程序进行详细的分析和解释。 首先,程序的目标是通过优化算法来解决一个多目标优化问题。程序中使用的优化算法是多目标粒子群优化算法(MOPSO),该算法通过迭代更新粒子的位置和速度来搜索最优解。 程序的主要功能是对能源系统进行优化调度,包括光伏发电、风力发电、储能和电网供电。程序的目标是最小化能源系统的成本,并满足负荷需求。 程序的主要思路是使用粒子群优化算法来搜索最优解。程序中定义了一个粒子类(Particle),每个粒子代

Global site tag (gtag.js) - Google Analytics