• 在qt中用tcp传输xml消息


    在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;
    }









  • 相关阅读:
    解决pgAdmin4启动失败方法
    X86汇编——计算斐波那契数列程序(详细注释和流程图说明)
    unity3d学习笔记(一) 第一人称视角实现和倒计时实现
    项目element-ui checkbox里面获取选中项 实现批量删除 修改
    //统计报表-供水量统计主列表分页查询 Element-ui的分页插件
    导出excel的功能效果实现
    echarts的基本使用以及如何使用官方实例的方法
    vue.js移动端app:初始配置
    使用雪碧图
    iconFont字体图标
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/3926962.html
Copyright © 2020-2023  润新知