现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

Qt网络编程:用tcp传输xml消息

2015-01-06 22:03 工业·编程 ⁄ 共 5437字 ⁄ 字号 暂无评论

环境:

主机: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

给我留言

留言无头像?