写了一个小的Qt网络程序,很简单,发送的网络消息除了字符串还有一个结构体。很简单的想到用memcpy()函数来将数据序列化为BYTE数组从而实现网络传输。

序列化是Java中一个概念,C中并没有,C++中后来引入了序列化和反序列化的概念。序列化是指将非系统类型的类的对象通过序列化操作转换成基本数据格式,从而达到便于网络传输或者文件读写的目的。反序列化是序列化的逆操作。

注:C/C++中BYTE与Char在内存中数据一样,形式相同,在Windef.h中有一行:

  typedef unsigned char BYTE;

故而,在内存中char和BYTE是一样的,序列化的目标为BYTE和char是等效的。

而QUdpSocket需要的是char型的网络传输格式,序列化的结果就是BYTE或者char型。

而序列化为char型,就不得不提C/C++中的内存对准问题,个人的经验是尽量多用char、BYTE等定长类型,少用int,double等变长类型,来进行序列化,因为在不同系统中,变长类型会因为系统的不同而定义为不同长度的内存位,进而系统会特定性的进行内存对齐,导致序列化后的反序列化出现乱码。

实在需要使用类似的结构或者类型,则尽量将其岔开,并且通过不同长度类型隔开来保证内存始终对齐至理想位置。并且,相对的,尽量将“较大”的类型变量靠前放置。

-------------------------------------------------------------------------------------------------------

现在描述遇到的问题:

  需求:通过Qt界面得到操作信息,并保存到一个结构体中,初始化一个UDPSocket对象,将结构体序列化为char型后,通过网络发送。

  实现:Qt界面通过QImage类的对象,得到图像信息并获取操作数据。自定义结构体如下:

 typedef struct tagDrawInfo
{
TOOLS m_Tool; /// 绘图工具;TOOLS为自定义enum联合体。
int width; /// 画笔宽度;
QColor lineColor; /// 线条颜色;
QColor fillColor; /// 填充颜色;
Qt::BrushStyle
brushStyle; /// 画刷风格;
QPoint startPoint; /// 开始点;
QPoint endPoint;  /// 结束点;
}DRAWINFO;

  通过memcpy()函数来实现内存拷贝,达到序列化的目的。

  问题:接收端得到的DRAWINFO对象,值为意料之外值,进而程序不能通过当前对象完成进一步操作。

  解决:1)自己定义序列化函数,将特定对象放置于指定位置,保证反序列化时数据位置和预期一样。分别对结构体的每部分序列化和反序列化,利用各类型的构造函数初始化对象,完成反序列化。

     2)对DRAWINFO定义顺序进行调整,对变长类型对象进行分离,确保系统内存的自动对齐不会对数据位置产生影响。更改过后的结构体定义如下:

 typedef struct tagDrawInfo
{
  Qt::BrushStyle
brushStyle; /// 画刷风格;
QPoint endPoint;  /// 结束点;
QColor fillColor; /// 填充颜色;
QColor lineColor; /// 线条颜色;
TOOLS m_Tool; /// 绘图工具;TOOLS为自定义enum联合体。
QPoint startPoint; /// 开始点;
int width; /// 画笔宽度;
}DRAWINFO;

  结果:对定义顺序进行调整后,接收端的DRAWINFO对象反序列化功能正常。

  分析:C++编译器,会对int型、bool型等边长类型进行内存对齐,提高内存利用效率,进而提高CPU一个工作周期内可处理指令条数,提高程序运行效率,但是在自动完成一些功能时会产生意外的问题,需要适当调整。

  而关于内存对准的问题,今天欠下一笔,日后有时间进行详解~

Qt中QUdpSocket序列化问题的更多相关文章

  1. QT中的线程与事件循环理解(1)

    1.需要使用多线程管理的例子 一个进程可以有一个或更多线程同时运行.线程可以看做是“轻量级进程”,进程完全由操作系统管理,线程即可以由操作系统管理,也可以由应用程序管理.Qt 使用QThread 来管 ...

  2. Qt 框架的图形性能高(OpenGL上的系统效率高),网络性能低,开发效率高,Quick是可以走硬件加速——Qt中分为好几套图形系统,差不多代表了2D描画的发展史。最经典的软描画系统

    -----图形性能部分-----Qt的widgets部分,运行时的图像渲染性能是一般的,因为大部分的界面内容都是Qt自绘,没有走硬件加速,也就是说很多图形内容都是CPU算出来的.但是widgets底层 ...

  3. 关于QT中的音频通信问题

    今天给大家讲说一个新的东西,使用QT实现音频通信的功能,挺起来是不是很高大上啊,哈哈,实际上我们只是使用一些接口做一些简单的工作而已,并不是让你写一个传输协议和采集音频信息,好了,那我们就来说一说关于 ...

  4. 4.关于QT中的QFile文件操作,QBuffer,Label上添加QPixmap,QByteArray和QString之间的区别,QTextStream和QDataStream的区别,QT内存映射(

     新建项目13IO 13IO.pro HEADERS += \ MyWidget.h SOURCES += \ MyWidget.cpp QT += gui widgets network CON ...

  5. QT中使用MinGW 编译的protobuf库--包含库的生成和使用

    QT中使用MinGW 编译的protobuf库--包含库的生成和使用 0前言 1准备工作 2生成protobuf库文件 3在QT中测试protobuf的使用 4结语 0前言 最近要在QT中使用prot ...

  6. Qt中使用Json

    Qt中使用Json需要一下几个类: QJsonValue            代表了json格式中的一个值 QJsonObject          代表了json格式的一个对象 QJsonArra ...

  7. 4.关于QT中的QFile文件操作,QBuffer,Label上加入QPixmap,QByteArray和QString之间的差别,QTextStream和QDataStream的差别,QT内存映射(

     新建项目13IO 13IO.pro HEADERS += \ MyWidget.h SOURCES += \ MyWidget.cpp QT += gui widgets network CON ...

  8. Qt 中使用Singleton模式需小心

    在qt中,使用Singleton模式时一定要小心.因为Singleton模式中使用的是静态对象,静态对象是直到程序结束才被释放的,然而,一旦把该静态对象纳入了Qt的父子对象体系,就会导致不明确的行为. ...

  9. qt中ui的 使用介绍

    1.什么是ui?ui通常是用Qt 设计师设计出来的界面文件的后缀.通常情况下ui是一个指向这个界面类的指针.ui-> 一般就是用来访问这个界面类里面的控件.例如你的ui文件里有一个叫okButt ...

随机推荐

  1. 如何利用phpize在生产环境中为php添加新的扩展php-bcmath

    在日常的开发当中,随着开发的功能越来越复杂.对运行环境的要求也就随着需求的变化需要不断地更新和变化.一个在线的生产系统不可能一开始就满足了所有的运行依赖,因此动态地添加依赖就显得比较必要了.如果你的应 ...

  2. 【linux】VMware12.0安装

    问题1:安装虚拟机时出现The Microsoft Runtime DLL installer failed to complete 解决: 重新安装,安装失败时不要点击结束,在开始“运行”出输入%t ...

  3. ios获取一个文件夹下的文件(夹)列表

    NSArray* ary=[[NSFileManager defaultManager] contentsOfDirectoryAtPath:[[NSBundle mainBundle] pathFo ...

  4. xtrabackup 增量备份(InnoDB)

    mysql> select * from users; +----+-----------+----------+--------------+ | id | name | password | ...

  5. 用VMware 11.0虚拟机安装Win8 系统失败,提示“shsucdx can't install”

    研究了好久,网上那些更改bios的方法根本行不通,因为该版本的biso根本没有SATA选项!解决方法很简单,如下图: 重启虚拟机即可.

  6. poj 1113:Wall(计算几何,求凸包周长)

    Wall Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 28462   Accepted: 9498 Description ...

  7. Java Hour4

    有句名言,叫做10000小时成为某一个领域的专家.姑且不辩论这句话是否正确,让我们到达10000小时的时候再回头来看吧. 本文作者Java 现经验约为3 Hour,请各位不吝赐教. Hour4 继承用 ...

  8. 开源的DevOps开发工具箱

    DevOps是一组过程.方法与系统的统称,用于促进开发(应用程序/软件工程).技术运营和质量保障(QA)部门之间的沟通.协作与整合.在DevOps的整个流程中,使用一些开源工具可以促进开发与运维之间的 ...

  9. mysql错误:“ Every derived table must have its own alias”(每个派生出来的表都必须有一个自己的别名)

    自我感悟: 由此可以延伸,我们得到一个结果集,可以通过as XXX的方式,把结果集给当作一张表来用,以实现子查询: 一般在多表查询时,会出现此错误. 因为,进行嵌套查询的时候子查询出来的的结果是作为一 ...

  10. GridView块布局

    <GridView android:id="@+id/gridview" android:layout_width="match_parent" andr ...