2021-2-2 1051 0
区块链学习

一、共识相关1、POW共识工作量证明,按劳分配,算力决定一切,谁的算力多,谁记账的概率就越大。具体:找到一个hash值SHA256(SHA256(Block_Header)),使得新区块头的哈希值小于某一个指定的值,即区块头中的“难度目标”。找到之后,会全网进行广播打包的区块进行验证,验证通过,该区块会被接受,从而记录到账本中。2、POS共识股权证明,根据用户持有货币的多少和时间(币龄),发放利息的制度。纯POS机制的加密货币,只能通过IPO的方式发行,这就导致“少数人”获得大量成本极低的加密货币。信用基础并不牢固。出块方式是通过随机数。3、DPOS权益持有者选举任何数量的见证人来生成区块,类似人民代表大会制度。即将POS中多有可记账改为只有选举出的见证者才可以记账。优点是交易确认时间短。二、HyperLedgerFabric共识算法1、solo模式单一order节点出块2、kafka模式3、拜占庭容错三、Hyperledger工作流程Fabric基本的流程包括四个阶段,分别是模拟(simulate)、排序(order)、验证(validata)、提交(commit)模拟如其名字所说的一样,这一阶段只是模拟进行交易,并不真正更新ledger。client发起交易请求,请求被发送至endorsers(endorsementpeer,这些peer是根据endorsementpolicy选出来的),endorsers根据当前本地的ledger状态并行模拟进行这些交易,虽然不改变ledger状态,但是会产生一个readset和一个writeset记录这个交易的影响,模拟完成后,endorser对readset和writeset进行签名并将其一起返回给client。如果client收到的readset和writeset是一致的(可能存在恶意endorser或者智能合约存在不确定的算法导致出现不一致),那么client就会生成一个真正的交易请求,包含readset、writeset和对应的签名,并将这个请求发送给orderingservice。排序orderingservice对来自client的交易进行排序,需要注意的是这里并不检查交易的内容,默认按照交易到达的顺序进行排序(这种简单的排序可能导致大量的交易冲突,降低性能,如果按某一特定的顺序排序可以极大的较少交易冲突,提高吞吐量,这也是这篇论文提出的最重要的工作,这里就不细说)。orderingservice将交易排序后打包成block,发送给网络中的peers,这里不保证所有的peer同时收到这个block,但保证收到的block的顺序是一致的(使用gossip协议)。验证当peer收到block后,就开始验证阶段。验证阶段主要包括两个检查:EndorsementPolicy检查检查交易是否满足endorsementpolicy以及是否包含有效的签名,否则说明交易可能被client或者恶意peer篡改过,直接丢弃。交易冲突检查检查交易之间是否存在冲突,也就是是否读脏数据的问题(某个交易在读取ledger之前,ledger被前一个交易改变了),如果存在就丢弃该交易。两次检查都通过的话就可以进入commit阶段了。提交peer将block添加到链上,注意这里是所有的交易(有效的和无效的)都加进来了。然后根据有效的交易改变当前的ledger状态。参考链接https://blog.csdn.net/yijiull/article/details/94966044

2021-1-28 1451 0
编程语言

本文代码托管于githubcmake_democmake中一些预定义变量PROJECT_SOURCE_DIR工程的根目录PROJECT_BINARY_DIR运行cmake命令的目录,通常是${PROJECT_SOURCE_DIR}/buildCMAKE_INCLUDE_PATH环境变量,非cmake变量CMAKE_LIBRARY_PATH环境变量CMAKE_CURRENT_SOURCE_DIR当前处理的CMakeLists.txt所在的路径CMAKE_CURRENT_BINARY_DIRtarget编译目录使用ADD_SURDIRECTORY(srcbin)可以更改此变量的值SET(EXECUTABLE_OUTPUT_PATH<新路径>)并不会对此变量有影响,只是改变了最终目标文件的存储路径CMAKE_CURRENT_LIST_FILE输出调用这个变量的CMakeLists.txt的完整路径CMAKE_CURRENT_LIST_LINE输出这个变量所在的行CMAKE_MODULE_PATH定义自己的cmake模块所在的路径SET(CMAKE_MODULE_PATH${PROJECT_SOURCE_DIR}/cmake),然后可以用INCLUDE命令来调用自己的模块EXECUTABLE_OUTPUT_PATH重新定义目标二进制可执行文件的存放位置LIBRARY_OUTPUT_PATH重新定义目标链接库文件的存放位置PROJECT_NAME返回通过PROJECT指令定义的项目名称CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS用来控制IFELSE语句的书写方式系统信息CMAKE_MAJOR_VERSIONcmake主版本号,如2.8.6中的2CMAKE_MINOR_VERSIONcmake次版本号,如2.8.6中的8CMAKE_PATCH_VERSIONcmake补丁等级,如2.8.6中的6CMAKE_SYSTEM系统名称,例如Linux-2.6.22CAMKE_SYSTEM_NAME不包含版本的系统名,如LinuxCMAKE_SYSTEM_VERSION系统版本,如2.6.22CMAKE_SYSTEM_PROCESSOR处理器名称,如i686UNIX在所有的类UNIX平台为TRUE,包括OSX和cygwinWIN32在所有的win32平台为TRUE,包括cygwin开关选项BUILD_SHARED_LIBS控制默认的库编译方式。如果未进行设置,使用ADD_LIBRARY时又没有指定库类型,默认编译生成的库都是静态库(可在t3中稍加修改进行验证)CMAKE_C_FLAGS设置C编译选项CMAKE_CXX_FLAGS设置C++编译选项cmake常用命令基本语法规则:cmake变量使用${}方式取值,但是在IF控制语句中是直接使用变量名环境变量使用$ENV{}方式取值,使用SET(ENV{VAR}VALUE)赋值指令(参数1参数2…)参数使用括弧括起,参数之间使用空格或分号分开。以ADD_EXECUTABLE指令为例:ADD_EXECUTABLE(hellomain.cfunc.c)或者ADD_EXECUTABLE(hellomain.c;func.c)指令是大小写无关的,参数和变量是大小写相关的。推荐你全部使用大写指令。部分常用命令列表:PROJECTPROJECT(projectname[CXX][C][Java])指定工程名称,并可指定工程支持的语言。支持语言列表可忽略,默认支持所有语言SETSET(VAR[VALUE][CACHETYPEDOCSTRING[FORCE]])定义变量(可以定义多个VALUE,如SET(SRC_LISTmain.cutil.creactor.c))MESSAGEMESSAGE([SEND_ERROR|STATUS|FATAL_ERROR]“messagetodisplay”…)向终端输出用户定义的信息或变量的值SEND_ERROR,产生错误,生成过程被跳过STATUS,输出前缀为—的信息FATAL_ERROR,立即终止所有cmake过程ADD_EXECUTABLEADD_EXECUTABLE(bin_file_name${SRC_LIST})生成可执行文件ADD_LIBRARYADD_LIBRARY(libname[SHARED|STATIC|MODULE][EXCLUDE_FROM_ALL]SRC_LIST)生成动态库或静态库SHARED动态库STATIC静态库MODULE在使用dyld的系统有效,若不支持dyld,等同于SHAREDEXCLUDE_FROM_ALL表示该库不会被默认构建SET_TARGET_PROPERTIES设置输出的名称,设置动态库的版本和API版本CMAKE_MINIMUM_REQUIREDCMAKE_MINIMUM_REQUIRED(VERSIONversion_number[FATAL_ERROR])声明CMake的版本要求ADD_SUBDIRECTORYADD_SUBDIRECTORY(src_dir[binary_dir][EXCLUDE_FROM_ALL])向当前工程添加存放源文件的子目录,并可以指定中间二进制和目标二进制的存放位置EXCLUDE_FROM_ALL含义:将这个目录从编译过程中排除SUBDIRSdeprecated,不再推荐使用(hellosample)相当于分别写ADD_SUBDIRECTORY(hello),ADD_SUBDIRECTORY(sample)INCLUDE_DIRECTORIESINCLUDE_DIRECTORIES([AFTER|BEFORE][SYSTEM]dir1dir2…)向工程添加多个特定的头文件搜索路径,路径之间用空格分隔,如果路径包含空格,可以使用双引号将它括起来,默认的行为为追加到当前头文件搜索路径的后面。有如下两种方式可以控制搜索路径添加的位置:CMAKE_INCLUDE_DIRECTORIES_BEFORE,通过SET这个cmake变量为on,可以将添加的头文件搜索路径放在已有路径的前面通过AFTER或BEFORE参数,也可以控制是追加还是置前LINK_DIRECTORIESLINK_DIRECTORIES(dir1dir2…)添加非标准的共享库搜索路径TARGET_LINK_LIBRARIESTARGET_LINK_LIBRARIES(targetlib1lib2…)为target添加需要链接的共享库ADD_DEFINITIONS向C/C++编译器添加-D定义ADD_DEFINITIONS(-DENABLE_DEBUG-DABC),参数之间用空格分隔ADD_DEPENDENCIESADD_DEPENDENCIES(target-namedepend-target1depend-target2…)定义target依赖的其他target,确保target在构建之前,其依赖的target已经构建完毕AUX_SOURCE_DIRECTORYAUX_SOURCE_DIRECTORY(dirVAR)发现一个目录下所有的源代码文件并将列表存储在一个变量中把当前目录下的所有源码文件名赋给变量DIR_HELLO_SRCSEXEC_PROGRAMEXEC_PROGRAM(Executable[dirwheretorun][ARGS<args>][OUTPUT_VARIABLE<var>][RETURN_VALUE<value>])用于在指定目录运行某个程序(默认为当前CMakeLists.txt所在目录),通过ARGS添加参数,通过OUTPUT_VARIABLE和RETURN_VALUE获取输出和返回值,如下示例#在src中运行ls命令,在src/CMakeLists.txt添加EXEC_PROGRAM(lsARGS"*.c"OUTPUT_VARIABLELS_OUTPUTRETURN_VALUELS_RVALUE)IF(notLS_RVALUE)MESSAGE(STATUS"lsresult:"${LS_OUTPUT})#缩进仅为美观,语法无要求ENDIF(notLS_RVALUE)INCLUDEINCLUDE(file[OPTIONAL])用来载入CMakeLists.txt文件INCLUDE(module[OPTIONAL])用来载入预定义的cmake模块OPTIONAL参数的左右是文件不存在也不会产生错误可以载入一个文件,也可以载入预定义模块(模块会在CMAKE_MODULE_PATH指定的路径进行搜索)载入的内容将在处理到INCLUDE语句时直接执行FIND_FIND_FILE(<VAR>namepath1path2…)VAR变量代表找到的文件全路径,包含文件名FIND_LIBRARY(<VAR>namepath1path2…)VAR变量代表找到的库全路径,包含库文件名FIND_LIBRARY(libXX11/usr/lib)IF(NOTlibx)MESSAGE(FATAL_ERROR"libXnotfound")ENDIF(NOTlibX)FIND_PATH(<VAR>namepath1path2…)VAR变量代表包含这个文件的路径FIND_PROGRAM(<VAR>namepath1path2…)VAR变量代表包含这个程序的全路径FIND_PACKAGE(<name>[major.minor][QUIET][NO_MODULE][[REQUIRED|COMPONENTS][componets…]])用来调用预定义在CMAKE_MODULE_PATH下的Find<name>.cmake模块,你也可以自己定义Find<name>模块,通过SET(CMAKE_MODULE_PATHdir)将其放入工程的某个目录供工程使用IF语法:IF(expression)COMMAND1(ARGS...)COMMAND2(ARGS...)...ELSE(expression)COMMAND1(ARGS...)COMMAND2(ARGS...)...ENDIF(expression)#一定要有ENDIF与IF对应IF(expression),expression不为:空,0,N,NO,OFF,FALSE,NOTFOUND或<var>_NOTFOUND,为真IF(notexp),与上面相反IF(var1ANDvar2)IF(var1ORvar2)IF(COMMANDcmd)如果cmd确实是命令并可调用,为真IF(EXISTSdir)IF(EXISTSfile)如果目录或文件存在,为真IF(file1IS_NEWER_THANfile2),当file1比file2新,或file1/file2中有一个不存在时为真,文件名需使用全路径IF(IS_DIRECTORYdir)当dir是目录时,为真IF(DEFINEDvar)如果变量被定义,为真IF(varMATCHESregex)此处var可以用var名,也可以用${var}IF(stringMATCHESregex)当给定的变量或者字符串能够匹配正则表达式regex时为真。比如:IF("hello"MATCHES"ell")MESSAGE("true")ENDIF("hello"MATCHES"ell")数字比较表达式IF(variableLESSnumber)IF(stringLESSnumber)IF(variableGREATERnumber)IF(stringGREATERnumber)IF(variableEQUALnumber)IF(stringEQUALnumber)按照字母表顺序进行比较IF(variableSTRLESSstring)IF(stringSTRLESSstring)IF(variableSTRGREATERstring)IF(stringSTRGREATERstring)IF(variableSTREQUALstring)IF(stringSTREQUALstring)一个小例子,用来判断平台差异:IF(WIN32)MESSAGE(STATUS“Thisiswindows.”)ELSE(WIN32)MESSAGE(STATUS“Thisisnotwindows”)ENDIF(WIN32)上述代码用来控制在不同的平台进行不同的控制,但是,阅读起来却并不是那么舒服,ELSE(WIN32)之类的语句很容易引起歧义。可以SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTSON)这时候就可以写成:IF(WIN32)ELSE()ENDIF()配合ELSEIF使用,可能的写法是这样:IF(WIN32)#dosomethingrelatedtoWIN32ELSEIF(UNIX)#dosomethingrelatedtoUNIXELSEIF(APPLE)#dosomethingrelatedtoAPPLEENDIF(WIN32)WHILE语法:WHILE(condition)COMMAND1(ARGS...)COMMAND2(ARGS...)...ENDWHILE(condition)其真假判断条件可以参考IF指令FOREACHFOREACH指令的使用方法有三种形式:列表语法:FOREACH(loop_vararg1arg2...)COMMAND1(ARGS...)COMMAND2(ARGS...)...ENDFOREACH(loop_var)示例:AUX_SOURCE_DIRECTORY(.SRC_LIST)FOREACH(F${SRC_LIST})MESSAGE(${F})ENDFOREACH(F)范围语法:FOREACH(loop_varRANGEtotal)COMMAND1(ARGS...)COMMAND2(ARGS...)...ENDFOREACH(loop_var)示例:从0到total以1为步进FOREACH(VARRANGE10)MESSAGE(${VAR})ENDFOREACH(VAR)输出:012345678910范围和步进语法:FOREACH(loop_varRANGEstartstop[step])COMMAND1(ARGS...)COMMAND2(ARGS...)...ENDFOREACH(loop_var)从start开始到stop结束,以step为步进,注意:直到遇到ENDFOREACH指令,整个语句块才会得到真正的执行。FOREACH(ARANGE5153)MESSAGE(${A})ENDFOREACH(A)输出:581114cmake中如何生成动态库和静态库参考ADD_LIBRARY和SET_TARGET_PROPERTIES用法t3示例cmake中如何使用动态库和静态库(查找库的路径)参考INCLUDE_DIRECTORIES,LINK_DIRECTORIES,TARGET_LINK_LIBRARIES用法t4示例使用动态库或静态库t5示例如何使用cmake预定义的cmake模块(以FindCURL.cmake为例演示)t6示例如何使用自定义的cmake模块(编写了自定义的FindHELLO.cmake)注意读t5和t6的CMakeLists.txt和FindHELLO.cmake中的注释部分cmake中如何指定生成文件的输出路径如上ADD_SUBDIRECTORY的时候指定目标二进制文件输出路径(推荐使用下面这种)使用SET命令重新定义EXECUTABLE_OUTPUT_PATH和LIBRARY_OUTPUT_PATH变量来指定最终的二进制文件的位置SET(EXECUTABLE_OUTPUT_PATH${PROJECT_BINARY_DIR}/bin)SET(LIBRARY_OUTPUT_PATH${PROJECT_BINARY_DIR}/lib)上面的两条命令通常紧跟ADD_EXECUTABLE和ADD_LIBRARY,与其写在同一个CMakeLists.txt即可cmake中如何增加编译选项使用变量CMAKE_C_FLAGS添加C编译选项使用变量CMAKE_CXX_FLAGS添加C++编译选项使用ADD_DEFINITION添加cmake中如何增加头文件路径参考INCLUDE_DIRECTORIES命令用法cmake中如何在屏幕上打印信息参考MESSAGE用法cmake中如何给变量赋值参考SET和AUX_SOURCE_DIRECTORY用法建议:在Project根目录先建立build,然后在build文件夹内运行cmake..,这样就不会污染源代码,如果不想要这些自动生成的文件了,只要简单的删除build文件夹就可以转载于https://blog.csdn.net/wzzfeitian/article/details/40963457/

2020-8-9 1768 0
2020-7-27 1111 0
区块链学习

1.理解记住最重要的一点,Dokcer实际是宿主机的一个普通的进程,这也是Dokcer与传统虚拟化技术的最大不同。Docker能保证运行环境的一致性,不会出现开发、测试、生产由于环境配置不一致导致的各种问题,一次配置多次运行。使用Docker,可更快地打包、测试以及部署应用程序,并可减少从编写到部署运行代码的周期。rootfs----内核空间是kernel,Linux刚启动时会加载bootfs文件系统,之后bootfs会被卸载掉。用户空间的文件系统是rootfs,包含我们熟悉的/dev,/proc,/bin等目录。对于容器的镜像来说,底层直接用Host的kernel,自己只需要提供rootfs就行了,容器是共享主机的kernel。先简单理解docker的使用过程,它分为镜像构建与容器启动。镜像构建:即创建一个镜像,它包含安装运行所需的环境、程序代码等。这个创建过程就是使用dockerfile来完成的。容器启动:容器最终运行起来是通过拉取构建好的镜像,通过一系列运行指令(如端口映射、外部数据挂载、环境变量等)来启动服务的。针对单个容器,这可以通过dockerrun来运行。而如果涉及多个容器的运行(如服务编排)就可以通过docker-compose来实现,它可以轻松的将多个容器作为service来运行(当然也可仅运行其中的某个),并且提供了scale(服务扩容)的功能。简单总结:1.dockerfile:构建镜像;2.dockerrun:启动容器;3.docker-compose:启动服务;2.安装更新ubuntu的apt源索引sudoapt-getupdate安装包允许apt通过HTTPS使用仓库sudoapt-getinstall\   apt-transport-https\    ca-certificates\   curl\   software-properties-common添加Docker官方GPGkeycurl-fsSLhttps://download.docker.com/linux/ubuntu/gpg|sudoapt-keyadd-设置Docker稳定版仓库sudoadd-apt-repository\    "deb[arch=amd64]https://download.docker.com/linux/ubuntu\    $(lsb_release-cs)\   stable"添加仓库后,更新apt源索引sudoapt-getupdate安装最新版DockerCE(社区版)sudoapt-getinstalldocker-ce检查DockerCE是否安装正确sudodockerrunhello-world如果终端卡在Unabletofindimage'hello-world:latest'locally位置docker在本地没有找到hello-world镜像,也没有从docker仓库中拉取镜像,出项这个问题的原因:是应为docker服务器再国外,我们在国内无法正常拉取镜像,所以就需要我们为docker设置国内阿里云的镜像加速器;需要修改配置文件/etc/docker/daemon.json如下{"registry-mirrors":["https://alzgoonw.mirror.aliyuncs.com"]}为了避免每次命令都输入sudo,可以设置用户权限,注意执行后须注销重新登录sudousermod-a-Gdocker$USER3.启动与停止安装完成Docker后,默认已经启动了docker服务,如需手动控制docker服务的启停,可执行如下命令#启动dockersudoservicedockerstart#停止dockersudoservicedockerstop#重启dockersudoservicedockerrestart参考文章理解Docker镜像分层

2020-7-14 1605 0
区块链学习

1.Protobuf简介protobuf是google提供的一个开源序列化框架,类似于XML,JSON这样的数据表示语言,其最大的特点是基于二进制,因此比传统的XML表示高效短小得多。虽然是二进制数据格式,但并没有因此变得复杂,开发人员通过按照一定的语法定义结构化的消息格式,然后送给命令行工具,工具将自动生成相关的类,可以支持php、java、c++、python等语言环境。通过将这些类包含在项目中,可以很轻松的调用相关方法来完成业务消息的序列化与反序列化工作。protobuf在google中是一个比较核心的基础库,作为分布式运算涉及到大量的不同业务消息的传递,如何高效简洁的表示、操作这些业务消息在google这样的大规模应用中是至关重要的。而protobuf这样的库正好是在效率、数据大小、易用性之间取得了很好的平衡。官方文档http://code.google.com/p/protobuf/2.Protobuf如何工作你首先需要在一个.proto文件中定义你需要做串行化的数据结构信息。每个ProtocolBuffer信息是一小段逻辑记录,包含一系列的键值对。这里有个非常简单的.proto文件定义了个人信息:messagePerson{requiredstringname=1;requiredint32id=2;optionalstringemail=3;enumPhoneType{MOBILE=0;HOME=1;WORK=2;}messagePhoneNumber{requiredstringnumber=1;optionalPhoneTypetype=2[default=HOME];}repeatedPhoneNumberphone=4;}有如你所见,消息格式很简单,每个消息类型拥有一个或多个特定的数字字段,每个字段拥有一个名字和一个值类型。值类型可以是数字(整数或浮点)、布尔型、字符串、原始字节或者其他ProtocolBuffer类型,还允许数据结构的分级。你可以指定可选字段,必选字段和重复字段。你可以在(http://code.google.com/apis/protocolbuffers/docs/proto.html)找到更多关于如何编写.proto文件的信息。一旦你定义了自己的报文格式(message),你就可以运行ProtocolBuffer编译器,将你的.proto文件编译成特定语言的类。这些类提供了简单的方法访问每个字段(像是query()和set_query()),像是访问类的方法一样将结构串行化或反串行化。例如你可以选择C++语言,运行编译如上的协议文件生成类叫做Person。随后你就可以在应用中使用这个类来串行化的读取报文信息。你可以这么写代码:Personperson;person.set_name("JohnDoe");person.set_id(1234);person.set_email("jdoe@example.com");fstream.output("myfile",ios::out|ios::binary);person.SerializeToOstream(&output);然后,你可以读取报文中的数据:fstreaminput("myfile",ios::in|ios:binary);Personperson;person.ParseFromIstream(&input);cout<<"Name:"<<person.name()<<endl;cout<<"E-mail:"<<person.email()<<endl;你可以在不影响向后兼容的情况下随意给数据结构增加字段,旧有的数据会忽略新的字段。所以如果使用ProtocolBuffer作为通信协议,你可以无须担心破坏现有代码的情况下扩展协议。你可以在API参考(http://code.google.com/apis/protocolbuffers/docs/reference/overview.html)中找到完整的参考,而关于ProtocolBuffer的报文格式编码则可以在(http://code.google.com/apis/protocolbuffers/docs/encoding.html)中找到。3.Protobuf消息定义要通信,必须有协议,否则双方无法理解对方的码流。在protobuf中,协议是由一系列的消息组成的。因此最重要的就是定义通信时使用到的消息格式。消息由至少一个字段组合而成,类似于C语言中的结构。每个字段都有一定的格式。字段格式:限定修饰符①|数据类型②|字段名称③|=|字段编码值④|[字段默认值⑤]①.限定修饰符包含required\optional\repeatedRequired:表示是一个必须字段,必须相对于发送方,在发送消息之前必须设置该字段的值,对于接收方,必须能够识别该字段的意思。发送之前没有设置required字段或者无法识别required字段都会引发编解码异常,导致消息被丢弃。Optional:表示是一个可选字段,可选对于发送方,在发送消息时,可以有选择性的设置或者不设置该字段的值。对于接收方,如果能够识别可选字段就进行相应的处理,如果无法识别,则忽略该字段,消息中的其它字段正常处理。---因为optional字段的特性,很多接口在升级版本中都把后来添加的字段都统一的设置为optional字段,这样老的版本无需升级程序也可以正常的与新的软件进行通信,只不过新的字段无法识别而已,因为并不是每个节点都需要新的功能,因此可以做到按需升级和平滑过渡。Repeated:表示该字段可以包含0~N个元素。其特性和optional一样,但是每一次可以包含多个值。可以看作是在传递一个数组的值。②.数据类型Protobuf定义了一套基本数据类型。几乎都可以映射到C++\Java等语言的基础数据类型.protobuf数据类型描述打包C++语言映射bool布尔类型1字节booldouble64位浮点数Ndoublefloat32为浮点数Nfloatint3232位整数、Nintuin32无符号32位整数Nunsignedintint6464位整数N__int64uint6464为无符号整Nunsigned__int64sint3232位整数,处理负数效率更高Nint32sing6464位整数处理负数效率更高N__int64fixed3232位无符号整数4unsignedint32fixed6464位无符号整数8unsigned__int64sfixed3232位整数、能以更高的效率处理负数4unsignedint32sfixed6464为整数8unsigned__int64string只能处理ASCII字符Nstd::stringbytes用于处理多字节的语言字符、如中文Nstd::stringenum可以包含一个用户自定义的枚举类型uint32N(uint32)enummessage可以包含一个用户自定义的消息类型NobjectofclassN表示打包的字节并不是固定。而是根据数据的大小或者长度。例如int32,如果数值比较小,在0~127时,使用一个字节打包。关于枚举的打包方式和uint32相同。关于message,类似于C语言中的结构包含另外一个结构作为数据成员一样。关于fixed32和int32的区别。fixed32的打包效率比int32的效率高,但是使用的空间一般比int32多。因此一个属于时间效率高,一个属于空间效率高。根据项目的实际情况,一般选择fixed32,如果遇到对传输数据量要求比较苛刻的环境,可以选择int32.③.字段名称字段名称的命名与C、C++、Java等语言的变量命名方式几乎是相同的。protobuf建议字段的命名采用以下划线分割的驼峰式。例如first_name而不是firstName.④.字段编码值有了该值,通信双方才能互相识别对方的字段。当然相同的编码值,其限定修饰符和数据类型必须相同。编码值的取值范围为1~2^32(4294967296)。其中1~15的编码时间和空间效率都是最高的,编码值越大,其编码的时间和空间效率就越低(相对于1-15),当然一般情况下相邻的2个值编码效率的是相同的,除非2个值恰好实在4字节,12字节,20字节等的临界区。比如15和16.1900~2000编码值为Googleprotobuf系统内部保留值,建议不要在自己的项目中使用。protobuf还建议把经常要传递的值把其字段编码设置为1-15之间的值。消息中的字段的编码值无需连续,只要是合法的,并且不能在同一个消息中有字段包含相同的编码值。建议:项目投入运营以后涉及到版本升级时的新增消息字段全部使用optional或者repeated,尽量不实用required。如果使用了required,需要全网统一升级,如果使用optional或者repeated可以平滑升级。⑤.默认值。当在传递数据时,对于required数据类型,如果用户没有设置值,则使用默认值传递到对端。当接受数据是,对于optional字段,如果没有接收到optional字段,则设置为默认值。关于importprotobuf接口文件可以像C语言的h文件一个,分离为多个,在需要的时候通过import导入需要对文件。其行为和C语言的#include或者java的import的行为大致相同。关于package避免名称冲突,可以给每个文件指定一个package名称,对于java解析为java中的包。对于C++则解析为名称空间。关于message支持嵌套消息,消息可以包含另一个消息作为其字段。也可以在消息内定义一个新的消息。关于enum枚举的定义和C++相同,但是有一些限制。枚举值必须大于等于0的整数。使用分号(;)分隔枚举变量而不是C++语言中的逗号(,)eg.enumVoipProtocol{H323=1;SIP=2;MGCP=3;H248=4;}

2020-4-22 1582 0