??xml version="1.0" encoding="utf-8" standalone="yes"?>精品综合久久久久久888蜜芽,久久夜色撩人精品国产,久久一区二区三区免费http://www.shnenglu.com/mmdengwo/category/16464.htmlzh-cnTue, 05 Apr 2011 10:58:05 GMTTue, 05 Apr 2011 10:58:05 GMT60protobuf在网l编E中的应用思?/title><link>http://www.shnenglu.com/mmdengwo/archive/2011/04/05/143466.html</link><dc:creator>沛沛</dc:creator><author>沛沛</author><pubDate>Tue, 05 Apr 2011 10:40:00 GMT</pubDate><guid>http://www.shnenglu.com/mmdengwo/archive/2011/04/05/143466.html</guid><wfw:comment>http://www.shnenglu.com/mmdengwo/comments/143466.html</wfw:comment><comments>http://www.shnenglu.com/mmdengwo/archive/2011/04/05/143466.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/mmdengwo/comments/commentRss/143466.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/mmdengwo/services/trackbacks/143466.html</trackback:ping><description><![CDATA[<span id="64oaqqm" class=Apple-style-span style="WORD-SPACING: 0px; FONT: medium Simsun; TEXT-TRANSFORM: none; COLOR: rgb(0,0,0); TEXT-INDENT: 0px; WHITE-SPACE: normal; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px"><span id="oasm2kw" class=Apple-style-span style="FONT-SIZE: 14px; LINE-HEIGHT: 21px; FONT-FAMILY: verdana, sans-serif; TEXT-ALIGN: left"> <h3 style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">protobuf?/h3> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">protobuf是google提供的一个开源序列化框架Q类gXMLQJSONq样的数据表CaQ其最大的特点是基于二q制Q因此比传统的XML表示高效短小得多。虽然是二进制数据格式,但ƈ没有因此变得复杂Q开发h员通过按照一定的语法定义l构化的消息格式Q然后送给命o(h)行工P工具自动生成相关的c,可以支持java、c++、python{语a环境。通过这些类包含在项目中Q可以很L的调用相x(chng)法来完成业务消息的序列化与反序列化工作?/p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">protobuf在google中是一个比较核?j)的基础库,作ؓ(f)分布式运涉?qing)到大量的不同业务消息的传递,如何高效z的表示、操作这些业务消息在googleq样的大规模应用中是臛_重要的。而protobufq样的库正好是在效率、数据大、易用性之间取得了(jin)很好的^衡?/p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">更多信息可参?a style="COLOR: rgb(51,102,153); TEXT-DECORATION: none" target=_blank>官方文档</a><br><span id="oeoiay4" class=Apple-style-span style="WORD-SPACING: 0px; FONT: medium Simsun; TEXT-TRANSFORM: none; COLOR: rgb(0,0,0); TEXT-INDENT: 0px; WHITE-SPACE: normal; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px"><span id="qee4gi2" class=Apple-style-span style="FONT-SIZE: 14px; LINE-HEIGHT: 21px; FONT-FAMILY: verdana, sans-serif; TEXT-ALIGN: left"></p> <h3 style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">例子介绍</h3> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">?a style="COLOR: rgb(51,102,153); TEXT-DECORATION: none" target=_blank>下蝲protobuf-2.3.0.zip</a>源代码库Q下载后解压Q选择vsprojects目录下的protobuf.sln解决Ҏ(gu)打开Q编译整个方案顺利成功。其中有一些测试工E,库相关的工程是libprotobuf、libprotobuf-lite、libprotoc和protoc。其中protoc是命令行工具。在example目录下有一个地址薄消息的例子Q业务消息的定义文g后缀?protoQ其中的addressbook.proto内容为:(x)</p> <pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)">package tutorial;</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"></pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)">option java_package = "com.example.tutorial";</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)">option java_outer_classname = "AddressBookProtos";</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"></pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)">message Person {</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> required string name = 1;</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> required int32 id = 2; // Unique ID number for this person.</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> optional string email = 3;</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"></pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> enum PhoneType {</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> MOBILE = 0;</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> HOME = 1;</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> WORK = 2;</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> }</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"></pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> message PhoneNumber {</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> required string number = 1;</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> optional PhoneType type = 2 [default = HOME];</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> }</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"></pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> repeated PhoneNumber phone = 4;</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)">}</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"></pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)">// Our address book file is just one of these.</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)">message AddressBook {</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> repeated Person person = 1;</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)">}</pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"></pre> </pre> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">该定义文Ӟ定义?jin)地址薄消息的l构Q顶层消息ؓ(f)AddressBookQ其中包含多个Person消息QPerson消息中又包含多个PhoneNumber消息。里面还定义?jin)一个PhoneType的枚丄型?/p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">cd前面有required表示必须Qoptional表示可选,repeated表示重复Q这些定义都是一目了(jin)然的Q无d说。关于消息定义的详细语法可参考官Ҏ(gu)档?br><br><span id="wsqsmsm" class=Apple-style-span style="WORD-SPACING: 0px; FONT: medium Simsun; TEXT-TRANSFORM: none; COLOR: rgb(0,0,0); TEXT-INDENT: 0px; WHITE-SPACE: normal; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px"><span id="sqgoyyg" class=Apple-style-span style="FONT-SIZE: 14px; LINE-HEIGHT: 21px; FONT-FAMILY: verdana, sans-serif; TEXT-ALIGN: left"></p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">现在用命令行工具来生成业务消息类Q切换到protoc.exe所在的debug目录Q在命o(h)行敲入:(x)</p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><font color=#0000ff>protoc.exe --proto_path=..\..\examples --cpp_out=..\..\examples ..\..\examples\addressbook.proto</font></p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">该命令中--proto_path参数表示.proto消息定义文g路径Q?-cpp_out表示输出c++cȝ路径Q后面接着是addressbook.proto消息定义文g。该命o(h)?x)读取addressbook.proto文gq生成对应的c++cd文g和实现文件。执行完后在examples目录生存?sh)(jin)addressbook.pb.h和addressbook.pb.cpp?/p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">现在新徏两个I控制台工程Q第一个不妨叫AddPersonQ然后把examples目录下的add_person.cc、addressbook.pb.h和addressbook.pb.cpp加入到该工程Q另一个工E不妨叫ListPersonQ将examples目录下的list_people.cc、addressbook.pb.h和addressbook.pb.cpp加入到该工程Q在两个工程的项目属性中附加头文件\?./src。两个工E的目依赖都选择libprotobuf工程Q库Q?/p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">lAddPerson工程d一个命令行参数比如叫addressbook.dat用于地址薄信息序列化写入该文Ӟ然后~译q行AddPerson工程Q根据提C入地址薄信?<br></p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><a style="COLOR: rgb(51,102,153); TEXT-DECORATION: none" ></a></p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><img src="http://www.shnenglu.com/images/cppblog_com/mmdengwo/1.gif" border=0><br>输入完成后,序列化到addressbook.dat文g中?/p> <span id="maaiqo2" class=Apple-style-span style="WORD-SPACING: 0px; FONT: medium Simsun; TEXT-TRANSFORM: none; COLOR: rgb(0,0,0); TEXT-INDENT: 0px; WHITE-SPACE: normal; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px"><span id="mqq44aa" class=Apple-style-span style="FONT-SIZE: 14px; LINE-HEIGHT: 21px; FONT-FAMILY: verdana, sans-serif; TEXT-ALIGN: left"> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">在ListPerson工程的命令行参数中加d文g参数..\AddPerson\addressbook.datQ然后在q行ListPerson工程Q可?list_people.cc的最后设个断点,避免命o(h)行窗口运行完后关闭看不到l果Q?br></p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><a style="COLOR: rgb(51,102,153); TEXT-DECORATION: none" ></a></p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"><img src="http://www.shnenglu.com/images/cppblog_com/mmdengwo/2.gif" border=0><br>写入地址薄的操作Q关键操作就是调用address_book.SerializeToOstreamq行序列化到文g?/p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">而读取操作中是address_book.ParseFromIstream从文件流反序列化Q这都是框架自动生成的类中的Ҏ(gu)?/p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">其他操作都是业务消息的字Dset/get之类的对象操作Q很明了(jin)。更详细的API参考官Ҏ(gu)档有详细说明?/p> <h3 style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px">在TCP|络~程中的考虑</h3> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">从上面的例子可以看出protobufq样的库是很方便高效的,那么自然的想到在|络~程中用来做业务消息的序列化、反序列化支持。在ZUDP协议的网l应用中Q由于UDP本n是有边界Q那么用protobuf来处理业务消息就很方ѝ但在TCP应用中,׃TCP协议没有消息边界Q这需要有一U机制来定业务消息边界。在TCP|络~程中这是必面对的问题?/p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">注意上面的address_book.ParseFromIstream调用Q如果流参数的内容多一个字节或者少一个字节,该方法都?x)返回失败(虽然某些字段可能正确得到l果?jin)?j)Q也是说送给反序列化的数据参数除?jin)格式正还必须有正的大小。因此在tcp|络~程中,要反序列化业务消息,p先知道业务数据的大小。而且在实际应用中可能在一个发送操作中Q发送多个业务消息,而且每个业务消息的大、类型都不一栗而且可能发送很大的数据?hu),比如文g?/p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">昄消息边界的确认问题和protobuf库无养Iq得自己搞定。在官方文档中也提到Qprotobufq不太适合来作大数据的处理Q当业务消息过1MӞ应该考虑是否应该用另外的替代Ҏ(gu)。当然对于大数据Q你也可以分割ؓ(f)多个块用protobuf做小块消息封装进行传递。但对很多应用这L(fng)作法昑־比较多余Q比如发送一个大的文Ӟ一般是在接收方从协议栈收到多少数据写多少数据到磁盘,q是一U边接收边处理的模式,q种模式基本上和每次收到的数据量没有关系。这U模式下再采用分割成消息进行反序列化就昑־多此一举了(jin)?/p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">׃每个业务消息的大和处理方式都可能不一P那么需要独立抽象出一个边界消息来区分不同的业务消息,而且q个边界消息的格式和大小必须固定。对于网l编E熟手,可能早已l想C(jin)q样的消息,我们可以l合protobuf库来定义一个边界消息,不妨叫BoundMsgQ?/p> </span></span><span id="ui4kqge" class=Apple-style-span style="WORD-SPACING: 0px; FONT: medium Simsun; TEXT-TRANSFORM: none; COLOR: rgb(0,0,0); TEXT-INDENT: 0px; WHITE-SPACE: normal; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px"><span id="quuasam" class=Apple-style-span style="FONT-SIZE: 14px; LINE-HEIGHT: 21px; FONT-FAMILY: verdana, sans-serif; TEXT-ALIGN: left"> <pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)">message BoundMsg </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)">{ </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> required int32 msg_type = 1; </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> required int32 msg_size = 2; </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)">}</pre> </pre> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">可以Ҏ(gu)需要扩充一些字D,但最基本的这两个字段够用了(jin)。我们只需要知道业务消息的cd和大即可。这个消息大是固定?字节Q专门用来确定数据流的边界。有?jin)这L(fng)边界消息Q在接收端处理Q何业务消息就很灵zL便了(jin)Q下面是接收端处理的单伪代码CZQ?/p> </span></span><span id="syiakcs" class=Apple-style-span style="WORD-SPACING: 0px; FONT: medium Simsun; TEXT-TRANSFORM: none; COLOR: rgb(0,0,0); TEXT-INDENT: 0px; WHITE-SPACE: normal; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px"><span id="0ec4kwg" class=Apple-style-span style="FONT-SIZE: 14px; LINE-HEIGHT: 21px; FONT-FAMILY: verdana, sans-serif; TEXT-ALIGN: left"> <pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"><span style="COLOR: rgb(0,0,255)">if</span>(net_read(buf,8)) </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)">{ </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> boundMsg.ParseFromIstream(buf); </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> <span style="COLOR: rgb(0,0,255)">switch</span>(boundMsg.msg_type) </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> { </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> <span style="COLOR: rgb(0,0,255)">case</span> BO_1: </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> <span style="COLOR: rgb(0,0,255)">if</span>(net_read(bo1Buf,boundMsg.msg_size)) </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> { </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> bo1.ParseFromIstream(bo1Buf); </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> .... </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> } </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> <span style="COLOR: rgb(0,0,255)">break</span>; </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> <span style="COLOR: rgb(0,0,255)">case</span> BO_2: </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> <span style="COLOR: rgb(0,0,255)">if</span>(net_read(bo2Buf,boundMsg.msg_size)) </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> { </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> bo2.ParseFromIstream(bo2Buf); </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> .... </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> } </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> <span style="COLOR: rgb(0,0,255)">break</span>; </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"></pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> <span style="COLOR: rgb(0,0,255)">case</span> FILE_DATA: </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> count = 0; </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> <span style="COLOR: rgb(0,0,255)">while</span>(count < boundMsg.msg_size) </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> { </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> piece_size = net_read(fileBuf,1024); </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> write_file(filename,fileBuf,piece_size); </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> count = count + piece_size; </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> } </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> <span style="COLOR: rgb(0,0,255)">break</span>; </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)"> } </pre> <pre style="FONT-SIZE: 12px; MARGIN: 0em; WIDTH: 844px; FONT-FAMILY: consolas, 'Courier New', courier, monospace; BACKGROUND-COLOR: rgb(255,255,255)">}</pre> </pre> </span></span><span id="u4s8m84" class=Apple-style-span style="WORD-SPACING: 0px; FONT: medium Simsun; TEXT-TRANSFORM: none; COLOR: rgb(0,0,0); TEXT-INDENT: 0px; WHITE-SPACE: normal; LETTER-SPACING: normal; BORDER-COLLAPSE: separate; orphans: 2; widows: 2; webkit-border-horizontal-spacing: 0px; webkit-border-vertical-spacing: 0px; webkit-text-decorations-in-effect: none; webkit-text-size-adjust: auto; webkit-text-stroke-width: 0px"><span id="m6cc6wm" class=Apple-style-span style="FONT-SIZE: 14px; LINE-HEIGHT: 21px; FONT-FAMILY: verdana, sans-serif; TEXT-ALIGN: left"> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">注意上面如果FILE_DATA消息后,q紧接其他业务消息的话,需要小?j),即count累计出的值可能大?/p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">boundMsg.msg_size的|那么多出来的实际上应该是下一个边界消息数据了(jin)。ؓ(f)?jin)避免处理的复杂性,上面所有的循环|络d操作Q上面BO_1QBO_2都可能需要@环读取,Z(jin)化没有写成@环)(j)的缓冲区位置和大参数应该动态调_(d)x(chng)ơ读取时传递的都是q期望读取的数据大小Q对于文件的话,可能Ҏ(gu)点,因ؓ(f)边读取边写入Q就没有必要事先要分配一个文件大的~冲区来存放数据?jin)。对于文件分配一个小~冲区来读,注意认下边界即可?/p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px">上面是我的一点考虑Q不妥之处还请大家讨Z。想惛_助于ACE、MINAq样的网l编E框Ӟ然后l合protobufq样的序列化框架Q网l编E中技术基设施层面的东西就l我们解军_差不多了(jin)Q我们可以真正只x(chng)于业务的实现?/p> <p style="PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 1em 0px 0.5em; PADDING-TOP: 0px"></span></span><br> </p> </span></span></span></span></span></span> <img src ="http://www.shnenglu.com/mmdengwo/aggbug/143466.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/mmdengwo/" target="_blank">沛沛</a> 2011-04-05 18:40 <a href="http://www.shnenglu.com/mmdengwo/archive/2011/04/05/143466.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Protocol Buffers Language Guide之proto文gcd格式分析[关键点翻译]http://www.shnenglu.com/mmdengwo/archive/2011/04/05/143465.html沛沛沛沛Tue, 05 Apr 2011 10:29:00 GMThttp://www.shnenglu.com/mmdengwo/archive/2011/04/05/143465.htmlhttp://www.shnenglu.com/mmdengwo/comments/143465.htmlhttp://www.shnenglu.com/mmdengwo/archive/2011/04/05/143465.html#Feedback0http://www.shnenglu.com/mmdengwo/comments/commentRss/143465.htmlhttp://www.shnenglu.com/mmdengwo/services/trackbacks/143465.html阅读全文

沛沛 2011-04-05 18:29 发表评论
]]>
Protocol Buffers介绍http://www.shnenglu.com/mmdengwo/archive/2011/04/05/143464.html沛沛沛沛Tue, 05 Apr 2011 10:26:00 GMThttp://www.shnenglu.com/mmdengwo/archive/2011/04/05/143464.htmlhttp://www.shnenglu.com/mmdengwo/comments/143464.htmlhttp://www.shnenglu.com/mmdengwo/archive/2011/04/05/143464.html#Feedback0http://www.shnenglu.com/mmdengwo/comments/commentRss/143464.htmlhttp://www.shnenglu.com/mmdengwo/services/trackbacks/143464.html

 转蝲?Protocol Buffers Language Guide之proto文gcd格式分析[关键点翻译] | 漂泊如风

今天来介l一?#8220;Protocol Buffers”Q以下简UprotobufQ这个玩意儿?span id=more-62 style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 12px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; VERTICAL-ALIGN: baseline; PADDING-TOP: 0px; BACKGROUND-COLOR: transparent; BORDER-RIGHT-WIDTH: 0px; outline-width: 0px; outline-style: initial; outline-color: initial; background-origin: initial; background-clip: initial">

?strong style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-WEIGHT: bold; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 12px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; VERTICAL-ALIGN: baseline; PADDING-TOP: 0px; BACKGROUND-COLOR: transparent; BORDER-RIGHT-WIDTH: 0px; outline-width: 0px; outline-style: initial; outline-color: initial; background-origin: initial; background-clip: initial">protobuf是啥玩意儿?
Z(jin)照顾从没听说q的同学Q照例先来扫盲一把?br>首先Qprotobuf是一个开源项目(官方站点?#8220;q里 ”Q,而且是后台很的开源项目。网上现有的大部分(臛_80%Q开源项目,要么是某人单qӀ要么是几个闲杂人等合伙搞。而protobuf则不?dng)它?鼎鼎大名的Google公司开发出来,q且在Google内部久经考验的一个东东。由此可见,它的作者绝非一般闲杂h{可比?br>那这个听h牛X的东东到底有啥用处捏Q简单地_(d)q个东东q的事儿其实和XML差不多,也就是把某种数据l构的信息,以某U格式保存v来。主要用于数据存储、传输协议格式等 场合。有同学可能?j)理犯嘀咕了(jin)Q放着好好的XML不用Q干嘛重新发明轮子啊Q!先别急,后面然会(x)有说道?br>话说C(jin)dQ大U是08q? 月)(j)QGoogleH然大发慈?zhn)Q把q个好东西A(ch)献给?jin)开源社区。这下,像俺q种喜欢捡现成的家伙可就有福啦!貌似喜欢捡现成的家伙q蛮多滴Q再加上 Google的号召力Q开源后不到一q_(d)protobuf的h气就已经很旺?jin)。所以俺Z(jin)与时pQ就单独开个帖子来忽?zhn)一把?/p>

?strong style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-WEIGHT: bold; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 12px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; VERTICAL-ALIGN: baseline; PADDING-TOP: 0px; BACKGROUND-COLOR: transparent; BORDER-RIGHT-WIDTH: 0px; outline-width: 0px; outline-style: initial; outline-color: initial; background-origin: initial; background-clip: initial">protobuf有啥特色Q?/strong>
扫盲完了(jin)之后Q就该聊一下技术方面的话题?sh)(jin)。由于这玩意儿发布的旉较短Q未满周岁)(j)Q所以俺接触的时间也不长。今天在此是先学现卖Q列位看官多多包?span class=Apple-converted-space> :-)

◇性能?效率?br>现在Q俺来说说Google公司为啥攄好端端的XML不用Q非要另L(fng)Ӟ重新造轮子。一个根本的原因是XML性能不够好?br>先说旉开销QXML格式化(序列化)(j)的开销倒还好;但是XML解析Q反序列化)(j)的开销׃敢恭l啦。俺之前l常到一些时间性能很敏感的场合Q由于不堪忍受XML解析的速度Q弃之如敝?br>再来看空间开销Q熟(zhn)XML语法的同学应该知道,XML格式Z(jin)有较好的可读性,引入?jin)一些冗余的文本信息。所以空间开销也不是太好(不过q点~点Q俺不常到Q?br>׃Google公司赖以吹嘘的就是它的v量数据和量处理能力。对于几十万、上百万机器的集,动不动就是PBU的数据量,哪怕性能E微提高0.1% 也是相当可观滴。所以Google自然无法容忍XML在性能上的明显~点。再加上Google从来׃~造轮子的牛hQ所以protobuf也就应运而生 ?jin)?br>Google对于性能的偏执,那可是出?jin)名的。所以,俺对于Google搞出来protobuf是非常滴攑ֿ(j)Q性能上不敢说是最好,但肯定不?x)太差?/p>

◇代码生成机?br>除了(jin)性能好,代码生成机制是主要吸引俺的地斏Vؓ(f)?jin)说明这个代码生成机ӞZD个例子?br>比如有个?sh)子商务的系l(假设用C++实现Q,其中的模块A需要发送大量的订单信息l模块BQ通讯的方式用socket?br>假设订单包括如下属性:(x)
Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-
旉QtimeQ用整数表示Q?br>客户idQuseridQ用整数表示Q?br>交易金额QpriceQ用点数表C)(j)
交易的描qͼ(x)descQ用字符串表C)(j)
Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-
如果使用protobuf实现Q首先要写一个proto文gQ不妨叫Order.protoQ,在该文g中添加一个名?#8221;Order”的messagel构Q用来描q通讯协议中的l构化数据。该文g的内容大致如下:(x)
Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-
message Order
{
required int32 time = 1;
required int32 userid = 2;
required float price = 3;
optional string desc = 4;
}
Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-

然后Q用protobuf内置的编译器~译 该proto。由于本例子的模块是C++Q你可以通过protobuf~译器的命o(h)行参敎ͼ?#8220;q里 ”Q,指定它生成C++语言?#8220;订单包装c?#8221;。(一般来_(d)一个messagel构?x)生成一个包装类Q?br>然后你用类g面的代码来序列化/解析该订单包装类Q?br>Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-

// 发送方
Order order;
order.set_time(XXXX);
order.set_userid(123);
order.set_price(100.0f);
order.set_desc(“a test order”);

string sOrder;
order.SerailzeToString(&sOrder);
// 然后调用某种socket的通讯库把序列化之后的字符串发送出?br>// ……

Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-
// 接收?br>string sOrder;
// 先通过|络通讯库接收到数据Q存攑ֈ某字W串sOrder
// ……

Order order;
if(order.ParseFromString(sOrder)) // 解析该字W串
{
cout << “userid:” << order.userid() << endl
<< “desc:” << order.desc() << endl;
}
else
{
cerr << “parse error!” << endl;
}
Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-Q-

有了(jin)q种代码生成机制Q开发h员再也不用吭哧吭哧地~写那些协议解析的代码了(jin)Q干q种zL典型的吃力不讨好Q?br>万一来需求发生变_(d)要求l订单再增加一?#8220;状?#8221;的属性,那只需要在Order.proto文g中增加一行代码。对于发送方Q模块AQ,只要增加一行设|状态的代码Q对于接收方Q模块BQ只要增加一行读取状态的代码。哇塞,直太L?jin)?br>另外Q如果通讯双方使用不同的编E语a来实玎ͼ使用q种机制可以有效保两边的模块对于协议的处理是一致的?br>Z跑题?sh)下?br>从某U意义上Ԍ可以把proto文g看成是描q通讯协议的规D明书Q或者叫接口规范Q。这U伎俩其实老早有?jin),搞过微Y的COM~程或者接触过CORBA的同学,应该都能从中看到IDLQ详l解释看“q里 ”Q的影子。它们的思想是相通滴?/p>

◇支?#8220;向后兼容”?#8220;向前兼容”
q是拿刚才的例子来说事儿。ؓ(f)?jin)叙q方便,俺把增加?#8220;状?#8221;属性的订单协议成ؓ(f)“新版?#8221;Q之前的?#8220;老版?#8221;?br>所谓的“向后兼容”Qbackward compatibleQ,是_(d)当模块B升?jin)之后,它能够正识别模块A发出的老版本的协议。由于老版本没?#8220;状?#8221;q个属性,在扩充协议时Q可以考虑?#8220;状?#8221;属性设|成非必?/strong> 的,或者给“状?#8221;属性设|一个缺省|如何讄~省|参见“q里 ”Q?br>所谓的“向前兼容”Qforward compatibleQ,是_(d)当模块A升?jin)之后,模块B能够正常识别模块A发出的新版本的协议。这时候,新增加的“状?#8221;属性会(x)被忽略?br>“向后兼容”?#8220;向前兼容”有啥用捏Q俺举个例子Q当你维护一个很庞大的分布式pȝӞ׃你无?strong style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-WEIGHT: bold; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 12px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; VERTICAL-ALIGN: baseline; PADDING-TOP: 0px; BACKGROUND-COLOR: transparent; BORDER-RIGHT-WIDTH: 0px; outline-width: 0px; outline-style: initial; outline-color: initial; background-origin: initial; background-clip: initial">同时 所?/strong> 模块Qؓ(f)?jin)保证在升q程中,整个pȝ能够可能不受媄(jing)响,需要尽量保证通讯协议?#8220;向后兼容”?#8220;向前兼容”?/p>

◇支持多U编E语a
俺开博以来点评的几个开源项目(比如“Sqlite ”?#8220;cURL ”Q,都是支持很多U?/strong> ~程语言_(d)q次的protobuf也不例外。在Google官方发布的源代码中包含了(jin)C++、Java、Python三种语言Q正好也是俺最常用的三U,真爽Q。如果你qx(chng)用的是q三U语a之一Q那好办了(jin)?br>假如你想把protobuf用于其它语言Q咋办捏Q由于Google一呼百应的号召力,开源社区对protobuf响应t跃Q近期冒出很多其它编E语a 的版本(比如ActionScript、C#、Lisp、Erlang、Perl、PHP、Ruby{)(j)Q有些语aq同时搞Z(jin)多个开源的目。具体细节可以参?#8220;q里 ”?br>不过俺有义务提醒一下在座的各位同学。如果你考虑把protobuf用于上述q些语言Q一定认真评估对应的开源库。因些开源库不是Google官方提供的、而且出来的时间还?sh)长。所以,它们的质量、性能{方面可能还有欠~?/p>

?strong style="BORDER-TOP-WIDTH: 0px; PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-WEIGHT: bold; BORDER-LEFT-WIDTH: 0px; FONT-SIZE: 12px; BORDER-BOTTOM-WIDTH: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px; VERTICAL-ALIGN: baseline; PADDING-TOP: 0px; BACKGROUND-COLOR: transparent; BORDER-RIGHT-WIDTH: 0px; outline-width: 0px; outline-style: initial; outline-color: initial; background-origin: initial; background-clip: initial">protobuf有啥~陷Q?/strong>
前几天刚刚在“光环效应 ”的帖子里?#8220;要同时评C点和~点”。所以俺最后再来批判一下这玩意儿的~点?br>◇应用不够广
׃protobuf刚公布没多久Q相比XML而言Qprotobufq属于初?gu)庐。因此,在知名度、应用广度等斚w都远不如XML。由于这个原因,假如你设计的pȝ需要提供若q对外的接口l第三方pȝ调用Q俺奉劝你暂时不要考虑protobuf格式?br>◇二q制格式D可读性差
Z(jin)提高性能Qprotobuf采用?jin)二q制格式q行~码。这直接D?jin)可L差的问题(严格地说Q是没有可读性)(j)。虽然protobuf提供?jin)TextFormatq个工具c(文档?#8220;q里 ”Q,但终I无法彻底解x(chng)问题?br>可读性差的危宻I俺再来D个例子。比如通讯双方如果出现问题Q极易导致扯皮(都不承认自己有问题,都说是对方的错)(j)。俺对付扯皮的一个简单方法就是直?抓包qdump成logQ能比较Ҏ(gu)地看出错误在哪一斏V但是protobuf的二q制格式Q导致你抓包q直接dump出来的log难以看懂?br>◇缺乏自描述
一般来_(d)XML是自描述的,而protobuf格式则不是。给你一D二q制格式的协议内容,如果不配合相应的proto文gQ那直就像天书一般?br>׃“~Z自描q?#8221;Q再加上“二进制格式导致可L差”。所以在配置文g斚wQprotobuf是肯定无法取代XML的地位滴?/p>

沛沛 2011-04-05 18:26 发表评论
]]>
þֹƷۺ| þþоƷ| ѾƷþþþþĻ| ޾ƷþþþĻ| ɫվwwwþþ| þ㽶һëƬ| ƷþþĻ| þþƷ99Ӱ | 97Ʒ˾þþô߽97| 99þѹػ| þþþþþƵ| þۺϺݺɫۺ| þþ뾫Ʒպý | 91Ƶ91þþ| ޾Ʒþþþþ| 99鶹þþùƷ | AëƬþ| þþþAVۺϲҰ| ƷþþþAV| ɫԭһþۺ| þ޹ҹƷƬ| ҹƷþþþþëƬ| 㽶99þùۺϾƷլ | ëƬŷëƬþþ| þһ99| Ʒ˾Ʒþþ| þŮƵ| Ʒþþþ| þþƷҹҹҹҹҹþ| ˾Ʒþ| ĻƷþ| ˾þô߽Ʒ| þþƷ޾Ʒ| ƷۺϾþ| ˾þۺ2020| 91þþƷ91þɫ| 99þ777ɫ| һɫþ88ձȡۺ| þŷձƷ| þþƷվ| Ʒþþþû|