qt中用tcp传输xml消息 good

本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.

 

环境:

主机:WIN7

开发环境:Qt5 3.1.2

说明:

在tcp上传输xml消息.

协议格式如下:

2字节标识(0xc55c,网络序)+2字节预留 +4字节报文内容长度(网络序) + 4字节命令字(网络序)+报文内容

部分协议:

命令字:
请求值班信息:GET_DUTY_INFO
请求报文:

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <request >  
  3. <identifier>客户端的唯一标识符</identifier>  
  4. </request>  


回复报文:

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <dutyinfo>  
  3.   <version>版本号</version>//表示车辆值班记录有无变化(如增减)  
  4.   <vehiclenum>车辆数目</vehiclenum>  
  5.     <vehicle>  
  6. <dutyofvehicleuid>32位UUID</dutyofvehicleuid>  
  7. <number>车辆编号, 如1,2,3,4</ number>  
  8. <platenumber>车牌号</platenumber>  
  9. <image>图片url</image>  
  10. <liquidlevel>78</liquidlevel>//0至100  
  11.     </vehicle>  
  12.     <vehicle>  
  13. <dutyofvehicleuid>32位UUID</dutyofvehicleuid>  
  14. <number>车辆编号, 如1,2,3,4</ number>  
  15. <platenumber>车牌号</platenumber>  
  16. <image>图片url</image>  
  17. <liquidlevel>78</liquidlevel>//0至100  
  18. </vehicle>  
  19. …  
  20. </dutyinfo>  

处理思路:

1.发送:

调用qt中处理xml文件的类将所需要发送的信息保存为xml文件,然后读取文件,将文件转化为字节流,并拼接帧头,然后发送

2.接收

将接收的字节流去掉帧头后保存为xml文件,然后调用qt中处理xml文件的类读取其中的信息

源代码:

保存为xml文件

[cpp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. //打开需要发送的xml命令  
  2.     QFile file(FILE_GET_DUTY_TX);  
  3.     //生成xml文件  
  4.     QDomDocument doc;  
  5.     QDomElement root_elem;  
  6.     QDomElement item;  
  7.     QDomText text;  
  8.   
  9.     //xml文件头  
  10.     QString header("version="1.0" encoding="UTF-8"");  
  11.     doc.appendChild(doc.createProcessingInstruction("xml",header));  
  12.   
  13.     //根元素  
  14.     root_elem = doc.createElement("request");  
  15.     doc.appendChild(root_elem);  
  16.   
  17.     //元素:identifier  
  18.     item = doc.createElement("identifier");  
  19.     text = doc.createTextNode(QString(Local_Id));  
  20.     item.appendChild(text);  
  21.     root_elem.appendChild(item);  
  22.   
  23.     //新建文件并保存  
  24.     file.open(QIODevice::WriteOnly);  
  25.     QTextStream out(&file);  
  26.     out.setCodec("UTF-8");  
  27.     doc.save(out,4,QDomNode::EncodingFromTextStream);  
  28.     file.close();  


读取xml文件,得到字节流

[cpp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. //读取xml文件  
  2.     file.open(QIODevice::ReadOnly);  
  3.     QTextStream get(&file);  
  4.     //得到xml数据  
  5.     Data_Xml_Tx = get.readAll().toLocal8Bit();  
  6.     file.close();  


发送函数

[cpp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. /********************************************************************* 
  2. *                               槽函数:发送网络帧 
  3. *参数:cmd:帧命令 
  4. *    frame:发送的报文 
  5. **********************************************************************/  
  6.   
  7. void Net::slot_net_tx_frame(int cmd,QByteArray frame)  
  8. {  
  9.     QByteArray head;  
  10.     int i = 0;  
  11.   
  12.     i = 0;  
  13.     //帧头  
  14.     head[i++] = 0xc5;  
  15.     head[i++] = 0x5c;  
  16.     //预留  
  17.     head[i++] = 0;  
  18.     head[i++] = 0;  
  19.     //报文长度  
  20.     head[i++] = frame.size() >> 24;  
  21.     head[i++] = frame.size() >> 16;  
  22.     head[i++] = frame.size() >> 8;  
  23.     head[i++] = frame.size();  
  24.     //命令字  
  25.     head[i++] = cmd >> 24;  
  26.     head[i++] = cmd >> 16;  
  27.     head[i++] = cmd >> 8;  
  28.     head[i++] = cmd;  
  29.     //组合帧  
  30.     frame.prepend(head);  
  31.   
  32.     //判断当前是否连接上服务器  
  33.     if (tcp_client->state() == QAbstractSocket::ConnectedState)  
  34.     {  
  35.         //已连接上  
  36.         //发送数据  
  37.         tcp_client->write(frame);  
  38.   
  39.     #ifdef DEBUG  
  40.         qDebug() << "发送网络帧1:cmd" << cmd;  
  41.     #endif  
  42.     }  
  43.     else  
  44.     {  
  45.         //未连接上  
  46.         Frame = frame;  
  47.         //连接服务器  
  48.         if (tcp_client->state() != QAbstractSocket::ConnectingState)  
  49.         {  
  50.             tcp_client->connectToHost(Server_Ip,Server_Port);  
  51.         }  
  52.     }  
  53. }  


tcp接收网络帧,并保存为xml文件,然后读取xml文件中的信息

[cpp] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. /********************************************************************* 
  2. *                               接收完成处理 
  3. **********************************************************************/  
  4.   
  5. void Get_Duty::deal_frame()  
  6. {  
  7.     int sum = 0;  
  8.     int i = 0;  
  9.     QSqlQuery q;  
  10.     QString version;  
  11.   
  12.     //解锁  
  13.     Lock_Net = 0;  
  14.     //放弃处理网络信息  
  15.     Net_Permission = 0;  
  16.   
  17.     qDebug() << "接收帧:回复值班信息";  
  18.   
  19.     //判断是否有值班信息  
  20.     if ((uint8_t)Frame.at(11) == 0)  
  21.     {  
  22.         //有标题,将数据存入xml文件  
  23.         //打开接收命令存储的xml文件  
  24.         QFile file(FILE_GET_DUTY_RX);  
  25.         //新建文件并保存  
  26.         file.open(QIODevice::WriteOnly);  
  27.         QTextStream out(&file);  
  28.         out.setCodec("UTF-8");  
  29.         out << Frame.mid(LEN_FRAME_HEAD);  
  30.         file.close();  
  31.   
  32.         //打开xml文件  
  33.         QDomDocument doc(FILE_GET_DUTY_RX);  
  34.         //获取文件内容  
  35.         file.open(QIODevice::ReadOnly);  
  36.         doc.setContent(&file);  
  37.         file.close();  
  38.   
  39.         //获得根节点  
  40.         QDomElement root_node = doc.documentElement();  
  41.         //获得第一个子节点:版本  
  42.         QDomNode node = root_node.firstChild();  
  43.         version = node.toElement().text();  
  44.         //判断版本号是否一致  
  45.         if (version == Version)  
  46.         {  
  47.             return;  
  48.         }  
  49.   
  50.         //不一致  
  51.         Version = version;  
  52.         qDebug() << "版本号" << Version;  
  53.   
  54.         //下一个子节点:车辆总数  
  55.         node = node.nextSibling();  
  56.         sum = node.toElement().text().toInt();  
  57.         qDebug() << "车辆总数" << sum;  
  58.   
  59.         //清空前3辆车辆信息  
  60.         Car_Three_List[0].clear();  
  61.         Car_Three_List[1].clear();  
  62.         Car_Three_List[2].clear();  
  63.         //清空值班信息表  
  64.         q.prepare("DELETE FROM duty");  
  65.         q.exec();  
  66.         //写入数据库  
  67.         for (i = 0;i < sum;i++)  
  68.         {  
  69.             node = node.nextSibling();  
  70.   
  71.             //插入数据  
  72.             q.prepare("INSERT INTO duty VALUES(?,?,?,?,?,?)");  
  73.             //uuid  
  74.             q.bindValue(0,node.toElement().childNodes().at(0).toElement().text());  
  75.             //编号  
  76.             q.bindValue(1,node.toElement().childNodes().at(1).toElement().text().toInt());  
  77.             //车牌  
  78.             q.bindValue(2,node.toElement().childNodes().at(2).toElement().text());  
  79.             //图片  
  80.             q.bindValue(3,node.toElement().childNodes().at(3).toElement().text());  
  81.             //汽油  
  82.             q.bindValue(4,node.toElement().childNodes().at(4).toElement().text().toInt());  
  83.             //图片标志  
  84.             q.bindValue(5,IMG_NULL);  
  85.             q.exec();  
  86.   
  87.             //前3辆车辆信息输入  
  88.             if (i < 3)  
  89.             {  
  90.                 Car_Three_List[i] = node.toElement().childNodes().at(0).toElement().text();  
  91.             }  
  92.         }  
  93.   
  94.         //打印数据库  
  95. //        q.prepare("SELECT * FROM duty");  
  96. //        q.exec();  
  97. //        while (q.next())  
  98. //        {  
  99. //            qDebug() << "uuid" << q.value(0).toString()  
  100. //                     << "编号" << q.value(1).toInt()  
  101. //                     << "车牌" << q.value(2).toString()  
  102. //                     << "图片" << q.value(3).toString()  
  103. //                     << "汽油" << q.value(4).toString()  
  104. //                     << "图片标志" << q.value(5).toInt();  
  105. //        }  
  106.     }  
  107.     else  
  108.     {  
  109.         Version = "null";  
  110.   
  111.         //清空值班信息表  
  112.         q.prepare("DELETE FROM duty");  
  113.         q.exec();  
  114.     }  
  115.   
  116.     //接收到值班信息  
  117.     emit sig_recv_duty_info();  
  118.   
  119.     //清空接收缓存  
  120.     Frame.clear();  
  121.     Len_Frame_Content = 0;  

http://blog.csdn.net/jdh99/article/details/38677811

原文地址:https://www.cnblogs.com/findumars/p/6152880.html