Chinaunix

标题: 如何设计一个消息帧的帧头 [打印本页]

作者: hiterator    时间: 2012-10-07 09:24
标题: 如何设计一个消息帧的帧头
本帖最后由 hiterator 于 2012-10-07 09:24 编辑

模块之间传递消息,可能跨网络,如何设计一个消息帧的头部?
各位大侠有没有相关的经验,可以参考下?


作者: wenlq    时间: 2012-10-07 11:04
消息长度,
消息mac,
节点id

作者: hiterator    时间: 2012-10-07 11:20
当前计划使用的消息帧:

消息开始字段(固定值)
消息标识(mac)               == 标识消息序列号
消息长度
节点id (这个应该是消息内容标识吧? 如果同时有请求消息和响应消息,使用相同格的帧头是否合适?)
标识本消息是否分帧标志 (如果消息体太长的话,可能有多帧,标识是否最后一帧,这个是否需要)

另外, 消息体一般如何定义? 如果消息体是struct类型的话,好像直接将struct发送出去比较不保险啊

回复 2# wenlq


   
作者: wenlq    时间: 2012-10-07 11:30
节点id 看你是否需要,我一个项目用于加解密取密钥的。
消息长度弄个网络字节序的long,长度可至4G。
消息体用struct非字符串的存在大小端问题,用xml吧。
作者: hiterator    时间: 2012-10-07 12:34
wenlq 发表于 2012-10-07 11:30
节点id 看你是否需要,我一个项目用于加解密取密钥的。
消息长度弄个网络字节序的long,长度可至4G。
消息 ...


这个主意不错  加解密这次就不去考虑了;

XML作为网络传输是个好主意,但会添加不少额外字符吧? 纠结
有没有更简单点的,直接发送的;
如果没有更好的,就直接每个struct加htonl转换了,就是难看点~

作者: __BlueGuy__    时间: 2012-10-07 12:45
本帖最后由 __BlueGuy__ 于 2012-10-07 12:46 编辑
hiterator 发表于 2012-10-07 12:34
这个主意不错  加解密这次就不去考虑了;

XML作为网络传输是个好主意,但会添加不少额外字符吧 ...


哎,XML 不过是个标记文本
网络传输传的是字节, 不是XML,XML 也会转换成字节的啊


作者: hiterator    时间: 2012-10-07 12:56
回复 6# __BlueGuy__


这个XML貌似扩展性好些,传输上效率上应该会差不少的


有没有方便扩展,传输效率高些的方法

当前准备这样扩展,每次有新消息,就准备在消息头里的 内容标识字段 新增加一个id;
消息体struct就每个都单独转换成网络序...


消息开始字段             == (固定值)
消息标识(mac)               == 标识消息序列号
消息长度
消息内容标识(节点id ??)      ==
标识本消息是否分帧标志

消息体struct1
消息体struct2
...





作者: __BlueGuy__    时间: 2012-10-07 13:01
你还没传输就考虑效率啊,

作者: liuspring6    时间: 2012-10-07 13:17
如果不是UDP啥的,没必要“标识本消息是否分帧标志”,如果是是私有协议通讯,个人觉着基础帧这样既可:“长度 + 校验码(可选) + 消息体”

其中消息体部分
文本方式:JSON/XML等(推荐json)
第三方库:protobuf/AMF3等(推荐protobuf)
自有协议:建议实现一个dictionary的序列化和反序列,用于传输。强烈不建议传输struct,后续增删修改代价很高。

消息体部分再包含其他信息(不全是数据区),如帧号、数据神马的
作者: hiterator    时间: 2012-10-07 14:05
回复 9# liuspring6


    明白人出现了 , 其实最后就是要实现一个自有协议类似的东东,方便添加扩展;

“实现一个dictionary的序列化和反序列” 有没有已经实现的例子   感谢//



作者: hiterator    时间: 2012-10-07 14:12
本帖最后由 hiterator 于 2012-10-07 14:47 编辑
liuspring6 发表于 2012-10-07 13:17
消息体部分再包含其他信息(不全是数据区),如帧号、数据神马的


把帧号分开和头部分开, 等于是又构造了一个消息头吧,为啥这样处理,好像不太好吧


另,当前使用的是TCP协议,就是要在TCP基础上造一个方便扩展和传输的自有格式;

作者: liuspring6    时间: 2012-10-07 15:58
关于dictionary的实现,这个东西不难,但是比较庞杂,一般来讲关联依赖比较多,不太好给,不过就是一个key=value结构,实现以下的序列化和反序列化,基本dictionary也块完工了
int、long long、string、date、bytearray,然后利用前面基础元素实现array、dictionary
这些的实现简单点说,无非就是个"类型 + 长度(可选,string、bytearray等需要) + 数据"
作者: liuspring6    时间: 2012-10-07 16:07
关于消息体部分还带有消非数据信息,主要是在实践中证明(至少我做的项目里出现了),随着需求的变更,消息包需要附带的信息还是有变化的,放在这部分便于后续调整。
而且这部分用dictionary实现,可以按照实际需要有时编码相关内容,有时不编码相关内容(接收方取默认值)。
例如:有小部分部分消息需要附带发送方的IP,而大部分消息不需要。帧号同理,我C2S就要帧号(确保数据包有序合法),但是S2S就无需帧号。
作者: tonghua209    时间: 2012-10-07 16:16
我觉得可以参考一下3GPP pdu串的定义一般应该够用了。呵呵。拙见。
作者: wwwsq    时间: 2012-10-08 10:06
本帖最后由 wwwsq 于 2012-10-08 10:11 编辑

有几种协议可以供楼主参考:
1,protobuf这是个不错的解决方案,很值得了解一下。通过IDL来定义数据协议,然后自动生成代码,所有模块立刻就有现成好用的代码可以打包、解包了。而且对ide的自动代码提示功能很友好,不容易出现打字错误。一般的公司直接用protobuf就很好了,大公司可以考虑结合自己的需求重建一个(可能会有跨编程语言、大数据、数据类型推导等特殊需求)。缺点是改协议不太方便,随便改点什么都有N个相关模块要发新版本。
2,金融行业的FIX协议。是很简单的一种dictionary协议,非常简洁,因此非常稳固。广泛应用于金融行业。是一个文本的协议。
3,json协议。打包解包的效率一般,对中文的支持不好,对二进制数据的支持不好。也是一个文本的协议。
4,xml协议,主要缺点是打包解包的效率比较低。xml和json都属于弱类型的协议,在处理float、double、bool、image之类的数据的时候不太清爽。
5,传统的定长结构,最好不要考虑。考虑用定长结构的人都应该用protobuf。


作者: linux_c_py_php    时间: 2012-10-08 11:52
本帖最后由 linux_c_py_php 于 2012-10-08 11:53 编辑

楼主如果仅仅是想做成: 头+体 的报文格式, 那我觉得你想怎么做都可以, 最快的是二进制头, 不需要考虑协议扩展性, 5分钟改一版, 真正的可扩展性是看程序架构, 而不是协议自身, 谁都避免不了改代码, 无非好的设计是加代码, 普通的设计是改代码.

楼主的意思是报文交互, 也就是内容总是一包一包的区分, 这种协议我觉得你自己觉得合适就行, 在这方面尤其推荐HTTP协议, 非常有利于程序扩展性, 因为HTTP本身是分布式的, 基于URL进行资源定位, 到了程序里就是基于URL的callback, 完全可以解耦, 推荐使用.

如果不希望有头, 那就需要使用带有"节"含义的协议, 比如XML, 它依靠本身的格式进行包划分, 不需要通知包长, 这就是与上面协议的最大区别.
XML开发成本稍大, 需要使用基于callback机制的expat库, 解析与应答XML Stanza进行交互, 适合长连接, 你如果喜欢XML风格的程序, 非常推荐使用.
作者: apachewebser    时间: 2012-10-08 15:30
高人啊            




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2