您的位置:首页 > 理论基础 > 计算机网络

在qt中用tcp传输xml消息

2016-06-08 16:39 549 查看
本文博客链接: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

 





<?xml version="1.0" encoding="UTF-8"?>  

<request >  

<identifier>客户端的唯一标识符</identifier>  

</request>  

回复报文:

[html] view
plain copy

 





<?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文件

[cpp] view
plain copy

 





//打开需要发送的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文件,得到字节流

[cpp] view
plain copy

 





//读取xml文件  

    file.open(QIODevice::ReadOnly);  

    QTextStream get(&file);  

    //得到xml数据  

    Data_Xml_Tx = get.readAll().toLocal8Bit();  

    file.close();  

发送函数

[cpp] view
plain copy

 





/********************************************************************* 

*                               槽函数:发送网络帧 

*参数: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文件中的信息

[cpp] view
plain copy

 





/********************************************************************* 

*                               接收完成处理 

**********************************************************************/  

  

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;  

}  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: