在qt中用tcp传输xml消息
本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明.
环境:
主机:WIN7
开发环境:Qt5 3.1.2
说明:
在tcp上传输xml消息.
协议格式例如以下:
2字节标识(0xc55c,网络序)+2字节预留 +4字节报文内容长度(网络序) + 4字节命令字(网络序)+报文内容
部分协议:
命令字:
请求值班信息:GET_DUTY_INFO
请求报文:
<?xml version="1.0" encoding="UTF-8"?> <request > <identifier>客户端的唯一标识符</identifier> </request>
回复报文:
<?xml version="1.0" encoding="UTF-8"?> <dutyinfo> <version>版本号号</version>//表示车辆值班记录有无变化(如增减) <vehiclenum>车辆数目</vehiclenum> <vehicle> <dutyofvehicleuid>32位UUID</dutyofvehicleuid> <number>车辆编号, 如1,2,3,4</ number> <platenumber>车牌号</platenumber> <image>图片url</image> <liquidlevel>78</liquidlevel>//0至100 </vehicle> <vehicle> <dutyofvehicleuid>32位UUID</dutyofvehicleuid> <number>车辆编号, 如1,2,3,4</ number> <platenumber>车牌号</platenumber> <image>图片url</image> <liquidlevel>78</liquidlevel>//0至100 </vehicle> … </dutyinfo>
处理思路:
1.发送:
调用qt中处理xml文件的类将所须要发送的信息保存为xml文件,然后读取文件,将文件转化为字节流,并拼接帧头,然后发送
2.接收
将接收的字节流去掉帧头后保存为xml文件,然后调用qt中处理xml文件的类读取当中的信息
源码:
保存为xml文件
//打开须要发送的xml命令 QFile file(FILE_GET_DUTY_TX); //生成xml文件 QDomDocument doc; QDomElement root_elem; QDomElement item; QDomText text; //xml文件头 QString header("version="1.0" encoding="UTF-8""); doc.appendChild(doc.createProcessingInstruction("xml",header)); //根元素 root_elem = doc.createElement("request"); doc.appendChild(root_elem); //元素:identifier item = doc.createElement("identifier"); text = doc.createTextNode(QString(Local_Id)); item.appendChild(text); root_elem.appendChild(item); //新建文件并保存 file.open(QIODevice::WriteOnly); QTextStream out(&file); out.setCodec("UTF-8"); doc.save(out,4,QDomNode::EncodingFromTextStream); file.close();
读取xml文件,得到字节流
//读取xml文件 file.open(QIODevice::ReadOnly); QTextStream get(&file); //得到xml数据 Data_Xml_Tx = get.readAll().toLocal8Bit(); file.close();
发送函数
/********************************************************************* * 槽函数:发送网络帧 *參数:cmd:帧命令 * frame:发送的报文 **********************************************************************/ void Net::slot_net_tx_frame(int cmd,QByteArray frame) { QByteArray head; int i = 0; i = 0; //帧头 head[i++] = 0xc5; head[i++] = 0x5c; //预留 head[i++] = 0; head[i++] = 0; //报文长度 head[i++] = frame.size() >> 24; head[i++] = frame.size() >> 16; head[i++] = frame.size() >> 8; head[i++] = frame.size(); //命令字 head[i++] = cmd >> 24; head[i++] = cmd >> 16; head[i++] = cmd >> 8; head[i++] = cmd; //组合帧 frame.prepend(head); //推断当前是否连接上server if (tcp_client->state() == QAbstractSocket::ConnectedState) { //已连接上 //发送数据 tcp_client->write(frame); #ifdef DEBUG qDebug() << "发送网络帧1:cmd" << cmd; #endif } else { //未连接上 Frame = frame; //连接server if (tcp_client->state() != QAbstractSocket::ConnectingState) { tcp_client->connectToHost(Server_Ip,Server_Port); } } }
tcp接收网络帧,并保存为xml文件,然后读取xml文件里的信息
/********************************************************************* * 接收完毕处理 **********************************************************************/ void Get_Duty::deal_frame() { int sum = 0; int i = 0; QSqlQuery q; QString version; //解锁 Lock_Net = 0; //放弃处理网络信息 Net_Permission = 0; qDebug() << "接收帧:回复值班信息"; //推断是否有值班信息 if ((uint8_t)Frame.at(11) == 0) { //有标题,将数据存入xml文件 //打开接收命令存储的xml文件 QFile file(FILE_GET_DUTY_RX); //新建文件并保存 file.open(QIODevice::WriteOnly); QTextStream out(&file); out.setCodec("UTF-8"); out << Frame.mid(LEN_FRAME_HEAD); file.close(); //打开xml文件 QDomDocument doc(FILE_GET_DUTY_RX); //获取文件内容 file.open(QIODevice::ReadOnly); doc.setContent(&file); file.close(); //获得根节点 QDomElement root_node = doc.documentElement(); //获得第一个子节点:版本号 QDomNode node = root_node.firstChild(); version = node.toElement().text(); //推断版本号号是否一致 if (version == Version) { return; } //不一致 Version = version; qDebug() << "版本号号" << Version; //下一个子节点:车辆总数 node = node.nextSibling(); sum = node.toElement().text().toInt(); qDebug() << "车辆总数" << sum; //清空前3辆车辆信息 Car_Three_List[0].clear(); Car_Three_List[1].clear(); Car_Three_List[2].clear(); //清空值班信息表 q.prepare("DELETE FROM duty"); q.exec(); //写入数据库 for (i = 0;i < sum;i++) { node = node.nextSibling(); //插入数据 q.prepare("INSERT INTO duty VALUES(?,?,?,?,?,?)"); //uuid q.bindValue(0,node.toElement().childNodes().at(0).toElement().text()); //编号 q.bindValue(1,node.toElement().childNodes().at(1).toElement().text().toInt()); //车牌 q.bindValue(2,node.toElement().childNodes().at(2).toElement().text()); //图片 q.bindValue(3,node.toElement().childNodes().at(3).toElement().text()); //汽油 q.bindValue(4,node.toElement().childNodes().at(4).toElement().text().toInt()); //图片标志 q.bindValue(5,IMG_NULL); q.exec(); //前3辆车辆信息输入 if (i < 3) { Car_Three_List[i] = node.toElement().childNodes().at(0).toElement().text(); } } //打印数据库 // q.prepare("SELECT * FROM duty"); // q.exec(); // while (q.next()) // { // qDebug() << "uuid" << q.value(0).toString() // << "编号" << q.value(1).toInt() // << "车牌" << q.value(2).toString() // << "图片" << q.value(3).toString() // << "汽油" << q.value(4).toString() // << "图片标志" << q.value(5).toInt(); // } } else { Version = "null"; //清空值班信息表 q.prepare("DELETE FROM duty"); q.exec(); } //接收到值班信息 emit sig_recv_duty_info(); //清空接收缓存 Frame.clear(); Len_Frame_Content = 0; }