1.UMX协议族
原来的UMX明确为UMX应用协议,增加CUMXT协议---UMX传输层协议.
数据传输时,如果需要指定传输属性,如是否存储转发,是否加密,固定投递,是否可靠等.
如此分层,有以下好处:
---逻辑清晰
---提高效率:中转时可以只解析到传输层,开销是固定的.
---便于扩展:破解之前UMX属性位缺少的困境
开发人员可以指定是否压缩.程序可以配置为应用消息包达到一个阈值时,自动对应用包压缩.
压缩配置:
在hotfox.conf的<transport>节点中配置
<transport>
<auto_compress enable="true" valve="64"/>
</transport>
默认自动压缩,valve=64.单位:K字节.
2.UMXT编程
对需要指定传输属性的消息的处理代码,需要修改.示例如下:
--原来的代码
CMsg *datamsg = new CMsg;
....
datamsg->SetMsgRL(RL_STRICT);
datamsg->SetMsgAttr(RECEIPT_MASK|FIXEDPOST_MASK); ///< 已经废除RECEIPT_MASK,FIXEDPOST_MASK,COMPRESS_MASK.
datamsg->SetMsgAttr(COMPRESS_MASK);
....
SendMsg(datamsg);
---用CUMXT对应用消息包(datamsg)进行封装
CUMXT *tmsg = CUMXT::New(datamsg);
tmsg->SetFwdFlag(RL_STRICT);///< 此消息需要传输确认,默认为RL_NODISCARDABLE
tmsg->SetAck2(true); ///< 此消息需要目标接收方确认
///< 固定投递默认为true
string ref_key = LogMsg("%d,%d,%d,%d,%s",GetDomain(),APP_DATA_BILL,SheetType,
(long)this->creator_==0?(long)Src_OrgID:(long)this->creator_,SheetID);
tmsg->SetRefKey(ref_key.c_str());///< 业务关联键,和具体的业务数据类型有关
tmsg->SetDataType(APP_DATA_BILL); ///< 数据类型为单据(应用数据类型统一定义,见bbox_datatype_def.h和<<SES全局资源分配规则.doc>>文档说明)
if (encrypt_flag_) { ///< 如果配置为加密单据
tmsg->SetEncrypt();
tmsg->SetCertEntity(Dest_OrgID);
}
SendMsg(tmsg); ///< 发送该消息
或者
CSEMQItem qe(tmsg); ///< 把此消息作为SEMQ队列元素
SaveMsgForForward(qe)) ///< 写入SEMQ
3.传输层和应用层通信
当底层消息发送出去或者对方确认后,可能需要通知应用层.应用层处理应用数据的状态或者主动发送一个通知给客户端.
为了消除传输和应用之间的耦合,通过事件模型实现.
有3个要素
3.1定义事件
事件统一编码,每种事件可以指定一个子类型.如数据发送事件定义如下:
#define DATA_SEND_OUT 12001 ///< 数据已发送
DATA_SEND_OUT的子类型有: 4-已执行数据发送 6-得到发送确认 7- 对确认的确认
对应DATA_SEND_OUT的事件对象为:
struct CDataSendoutEvent : public CEventBase {
unsigned long data_type_; ///< 数据类型
string ref_; ///< 事件参数,多个参数项之间用","分隔.不同的数据类型自行定义
CDataSendoutEvent(CQQ_EVENT_TYPE sub_type=4):CEventBase(DATA_SEND_OUT,sub_type),data_type_(0) {
}
};
3.2注册事件处理者
(1)事件处理者实现IEventHandler接口的handle_event方法.
(2)注册事件处理者:
event_controller_->register_handler(DATA_SEND_OUT,this);
(3)事件处理函数
int CLMPlugin::handle_event(EVENT_TYPE e,void *arg) {
switch(e) {
case DATA_SEND_OUT: { ///< 单据已发送
CDataSendoutEvent *e = (CDataSendoutEvent*)arg;
if (e->data_type_==APP_DATA_BILL) { ///< 只处理单据
vector<string> vs;
int sz = SplitString(e->ref_.c_str(),vs,',');///域,数据类型,单据类型,制单机构ID,单据编号
if (sz!=5)
return -1;
short status = e->sub_type_;
return UpdateSheetTableStatus(status,atol(vs[2].c_str()),atol(vs[3].c_str()),vs[4]);
}
}
}
return 0;
}
3.3激发事件
int CLocalSEMQ::PostSend(SHORT_SEMQ_RECORD *ssr) {
if (!ssr->ref_key_.empty()) { ///< 如果有应用关联键,则激发数据发送事件(DATA_SEND_OUT)
CDataSendoutEvent *e = new CDataSendoutEvent;
e->data_type_ = ssr->type_; ///< 数据类型
e->ref_ = ssr->ref_key_;
if (CBasePluginModule::event_controller_->pulse(DATA_SEND_OUT,e)) {
return -1;
}
}
return 0;
}