环境:
主机: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);
//判断当前是否连接上服务器
if (tcp_client->state() == QAbstractSocket::ConnectedState)
{
//已连接上
//发送数据
tcp_client->write(frame);
#ifdef DEBUG
qDebug() << "发送网络帧1:cmd" << cmd;
#endif
}
else
{
//未连接上
Frame = frame;
//连接服务器
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;
}
作者:jdh99