写了一个小的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. 安装完mysql后用root不能su成mysql

    现象: debian的机器用aptitude install mysql-server-5.1 后,用id mysql 可看出已经建了mysql用户,但是用root来su mysql 不成功,/var ...

  2. Android开发数据库三层应用-DataSnap

    Android开发数据库三层应用-DataSnap http://www.2ccc.com/news/Html/?1517.html 核心提示:我觉得Delphi最强大的的功能之一就是开发数据库三层应 ...

  3. 部署django应用

    Autor: wangxianlong 2016/7/10 16:17:55 环境: centos 6.5 python 2.7.5 django 1.9 nginx 1.8 selinux diab ...

  4. [Android Pro] 超能RecyclerView组件使用

    RecyclerView最强大的功能在于秒变功能,只需要改动很少的代码就可以实现ListView,GridView及水平ListViw的切换功能 public class MainActivity e ...

  5. Fedora 启动sshd服务:

    .先确认是否已安装ssh服务: [root@localhost ~]# rpm -qa | grep openssh-server openssh-server-.3p1-.fc12.i686 (这行 ...

  6. 打开genesis时一直在等待,后出现Timeout in communication read解决方法

    运行输入:netsh winsock reset 然后重启电脑

  7. Merge和Rebase在Git中的区别

    git命令Merge和Rebase的区别 git merge 会生成一个新得合并节点,而rebase不会 比如: D---E test / A---B---C---F master 使用merge合并 ...

  8. Java Hour 39 Maven ( 1 )

    有句名言,叫做10000小时成为某一个领域的专家.姑且不辩论这句话是否正确,让我们到达10000小时的时候再回头来看吧. Hour 39 Maven 1 Perhaps you are running ...

  9. SAE上传web应用(包括使用数据库)教程详解及问题解惑

    转自:http://blog.csdn.net/baiyuliang2013/article/details/24725995 SAE上传web应用(包括使用数据库)教程详解及问题解惑: 最近由于工作 ...

  10. zookeeper 4 letter 描述与实践

    命令示例描述 Conf echo conf | nc localhost 2181 (New in 3.3.0)输出相关服务配置的详细信息.比如端口.zk数据及日志配置路径.最大连接数,session ...