我在写一个通讯程序,报文这一块我的想法是通过xml来进行管理,这样可以方便的进行配置和修改。
这个想法的起因是我看到不少银行中间业务平台都能够方便的进行通讯报文的修改和配置。我的这个虽然是个小程序,
但我也想实现这样的功能,为将来的软件发展提供一个较好的体系结构。
最开始我的想法是这样的:
对每一个报文定义类似下面的一个xml结构
<Msg>
<ID>1</ID>
<Type>1</Type>
<Name>签到交易</Name>
<AnsMsgGrpID>2</AnsMsgGrpID>
<Direct>0</Direct>
<Fields>
<Field>
<ID>1</ID>
<Type>1</Type>
<DataType>1</DataType>
<Name>续包标志</Name>
<Len>1</Len>
</Field>
<Field>
<ID>2</ID>
<Type>2</Type>
<DataType>1</DataType>
<Name>交易码</Name>
<Len>4</Len>
</Field>
<Field>
</Field>
<Fields>
</Msg>
对应的,我在程序中定义结束报文配置信息的数据结构如下:
struct typFld
{
intiID;//字段序号
intiType;//字段类型
intiDataType;//字段数据类型 1-字符型;2-网络字节序
char*sFldNm;//字段名称
intiLen;//字段的长度
}
struct typFlds
{
intiCnt;//报文中字段的数目
struct typFld *FldPtr;//在程序中动态分配空间
}
struct typMsg
{
intiMsgID;//报文ID
int iType;//报文类型
char *sMsgNm;//报文名称
int iAnsMsgID;//回应报文的报文ID
int iDirect;//报文的方向,0--传入;1--传出
struct typFlds *FldsPtr;//指向存储各字段的配置信息的存储区域的指针
};
但是后来我发现报文中有一些特殊情况,采用上面的方式是不能处理的,如:
有一些报文段是需要循环的,具体循环的次数是在程序运行中才能知道的,比如说,用户多个月的欠费明细就是这种情况。
还有,有一些报文段是可能有,可能没有的,比如说:如果用户有欠费,回应报文中就会有用户各月的欠费明细,
如果用户没有欠费,回应报文就只返回一个错误码,而没有任何的欠费明细,这些情况可能会混合起来,我觉得就比较麻烦了,
我上网请教了一些朋友后,目前的思路是这样的:
报文的xml结构如下:
<Msg>
<ID>1</ID>
<Type>1</Type>
<Name>签到交易</Name>
<AnsMsgGrpID>2</AnsMsgGrpID>
<Direct>0</Direct>
<Fields>
<Field>
<ID>1</ID>
<Type>1</Type>
<DataType>1</DataType>
<Name>续包标志</Name>
<Len>1</Len>
</Field>
<Field>
<ID>2</ID>
<Type>2</Type>
<DataType>1</DataType>
<Name>交易码</Name>
<Len>4</Len>
</Field>
<While>
<If>一个条件表达式<If>
<Loop>
<iLpCnt>iQianFeiMonth</iLpCnt>
<Field>
<ID>3</ID>
<Type>2</Type>
<DataType>1</DataType>
<Name>欠费明细</Name>
<Len>10</Len>
</Field>
</Loop>
</While>
<Field>
</Field>
<Fields>
</Msg>
因为Fields节点中现在有不同的节点了:Field,While,Loop,有些朋友的意见是在Field节点中使用链表的形式。
我考虑了一下,觉得链表的编程太繁琐,还是希望使用数组的形式。编程简单。
对应的程序中的结构修改如下:
struct typFld
{
intiType;//0-报文字段1-循环开始2-循环结束3-条件开始4-条件结束
char*sLpCnt;//循环次数表达式
char *sWhile;//条件表达式
intiID;//字段序号
intiFldType;//字段类型
intiDataType;//字段数据类型 1-字符型;2-网络字节序
char*sFldNm;//字段名称
intiLen;//字段的长度
}
这样定义一个统一的大的结构
当在程序中使用的时候,比如说,根据定义的报文结构读取一个报文时,
如果读到一个"Field"节点,就根据这个节点的属性读取相应长度的字段;
如果读到一个"While"节点,就转化<if>子节点中的条件表达式,如果表达式为真,就读取while中的其他子节点,如果为假,就跳到<While>节点的下一个兄弟节点;
如果读到一个"Loop"节点,就根据<iLpCnt>节点中的表达式的值重复读取<Loop>中的其他子节点。
我这样的想法如何?有什么不对或者不妥的地方吗?欢迎大家讨论。
我使用的开发环境是sco unix +c +lib2xml
兄弟节点和子节点的查找,遍历方法lib2xml提供了,所以我就不用在结构中定义了
谢谢! |