XML格式的数据适合用于C程序与其他程序的通信,尝试拟定登录相关的报文格式,与服务端程序进行通信。
目录
- 通信内容格式约定
- 程序效果
- 业务流程
- 关键代码
- 参考资料
通信内容格式约定
1.发送请求时,都必须提供3个基本要素(大小写敏感)
要素 | 说明 |
---|---|
transName | 请求类型 |
Plain | 请求数据明文 |
Signature | 请求数据明文签名 |
2.登录请求Plain内容
要素 | 说明 |
---|---|
TransName | 请求类型 |
TransTime | 请求时间 |
UserNo | 用户名 |
UserPwd | 密码 |
3.登录应答Plain内容
要素 | 说明 |
---|---|
TransName | 请求类型 |
TransCode | 返回码 |
TransMsg | 返回信息 |
VerState | 验证结果 0-成功 1-失败 |
程序效果
请求报文目前被解析判断的只有类型、用户名、密码3个字段,只有“Tom/123456”能登录成功,其他用户名与密码的组合会分别报错“用户名不存在”、“密码错误”。
业务流程
![](https://img-blog.csdnimg.cn/202005172206124.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3UwMTMwMjU5NTU=,size_16,color_FFFFFF,t_70)
关键实现
1.内存读取XML数据样例-从报文中读取请求类型
int oltpRequest(char *psMsg, int size)
{
int iRet = 0;
xmlDocPtr doc = NULL;
xmlNodePtr cur = NULL;
xmlChar *key = NULL;
/* 从内存中解析生成XML的DOC文档结构 */
doc = xmlParseMemory(psMsg, size);
if (NULL == doc)
{
printf("xmlParseMemory error!\n");
return -1;
}
/* 获取XML的根节点 */
cur = xmlDocGetRootElement(doc);
if (NULL == cur)
{
printf("xmlDocGetRootElement error!\n");
return -1;
}
/* 获取XML的根节点的第一个子节点,并循环读取进行遍历 */
cur = cur->xmlChildrenNode;
while (cur != NULL)
{
/* 子节点名称为“transName”时,获取请求类型值 */
if (!xmlStrcmp(cur->name, (const xmlChar *)"transName"))
{
key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);
printf("transName:%s\n", key);
}
cur = cur->next;
}
key = NULL;
cur = NULL;
xmlFreeDoc(doc);
}
报文结构简单,没有复杂的嵌套关系,根节点往下一层循环就能读取所有的内容。
从transName标签获取得到“FMLG”,判断之后调用登录处理流程即可。
2.构造应答报文样例-生成应答报文
int xmlCreateIppv(char *psMsg, int *size)
{
/* 创建XML的DOC文档结构,并挂接“packet”根节点 */
xmlDocPtr docOut = xmlNewDoc(BAD_CAST"1.0");
xmlNodePtr root_node_out = xmlNewNode(NULL, BAD_CAST"packet");
xmlDocSetRootElement(docOut, root_node_out);
xmlChar *out_txt_ptr = NULL;
int doc_txt_len = 0;
/* 添加3个子节点 */
xmlNewChild(root_node_out, NULL, BAD_CAST"transName", (xmlChar *)"FMLG");
xmlNewChild(root_node_out, NULL, BAD_CAST"Plain", (xmlChar *)"TransName=FMLG|TransCode=00000000|TransMsg=login success.|VerState=0");
xmlNewChild(root_node_out, NULL, BAD_CAST"Signature", (xmlChar *)"502E9E38");
/* 将DOC文档结构写入字符串 */
xmlDocDumpFormatMemoryEnc(docOut, &out_txt_ptr, &doc_txt_len, "UTF-8", 0);
memcpy(psMsg, out_txt_ptr, doc_txt_len);
*size = doc_txt_len;
xmlFree(out_txt_ptr);
root_node_out = NULL;
xmlFreeDoc(docOut);
return 0;
}
客户端看到应答报文,说明C程序单元测试流程打通。
Tips:调用的libxml2库函数的接口可在参考资料的官网中查询使用方法。
参考资料
1.libxml2官网