在qt中用tcp传输xml消息

摘要:
˃客户端的唯一标识符回复消息:版本号//它指示车辆负载记录是否已更改(例如增加或减少)车辆数量32位UUID˃车辆编号,例如,1,2,3,4˂车牌号图片url78//0至10032位UUID车牌号,例如,1,2,3,14˂plate number˂/tablenumber/image˃78//0至100

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



免责声明:文章转载自《在qt中用tcp传输xml消息》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇如果在html触发点击事件不起作用TCP内核参数下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Linux网络编程笔记(修订版)

我的网络编程笔记, 因为最近又要做Linux下的网络编程,故重新修订, 其中一些内容参考了文末的链接及文章 1.   基本概念 2.   基本接口 2.1.   打开一个socket 2.2.   将socket绑定定指定的端口—bind 2.3.   侦听socket—listen (服务器端) 2.4.   等待接收请求—accept (服务器端) 2...

RabbitMQ(3) Spring boot集成RabbitMQ

springboot集成RabbitMQ非常简单,如果只是简单的使用配置非常少,springboot提供了spring-boot-starter-amqp项目对消息各种支持。 资源代码:练习用的代码。 https://github.com/xiaozhuanfeng?tab=repositories 简单使用 1、配置pom包,主要是添加spring-b...

Linux下高并发socket最大连接数各种限制的调优

1、修改用户进程可打开文件数限制  在Linux平台上,无论编写客户端程序还是服务端程序,在进行高并发TCP连接处理时,最高的并发数量都要受到系统对用户单一进程同时可打开文件数量的限制(这是因为系统为每个TCP连接都要创建一个socket句柄,每个socket句柄同时也是一个文件句柄)。可使用ulimit命令查看系统允许当前用户进程打开的文件数限制: [s...

Celery学习---Celery 分布式队列介绍及安装

 Celery介绍和基本使用 Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery, 举几个实例场景中可用的例子: 1. 你想对100台机器执行一条批量命令,可能会花很长时间 ,但你不想让你的程序等着结果返回,而是给你返回 一个任务ID,...

java中使用MD5进行加密(转)

   在各种应用系统的开发中,经常需要存储用户信息,很多地方都要存储用户密码,而将用户密码直接存储在服务器上显然是不安全的,本文简要介绍工作中常用的 MD5加密算法,希望能抛砖引玉。(一)消息摘要简介    一个消息摘要就是一个数据块的数字指纹。即对一个任意长度的一个数据块进行计算,产生一个唯一指印(对于SHA1是产生一个20字节的二进制数组)。消息摘要是...

Window API 之 PostMessage (消息投递)

PostMessage: 将一条消息投递到指定窗口的消息队列。投递的消息会在Windows事件处理过程中得到处理。 在那个时候,会随同投递的消息调用指定窗口的窗口函数。特别适合那些不需要立即处理的 窗口消息的发送返回值 。自己的理解是:通过这个函数,可以将自己想发送的消息发送到你想发送的窗口。就好比是两个人在发短信,那么这个函数就相当于是一部手机。查找资料...