Qt项目小记

项目需求IOS Pad 、IOS Phone、Android Pad、Android Phone与电脑的互动,主要完成Pad端远距离操作电脑,操作PPT播放等。

局域网互联,有Wifi即可。我负责PC端服务器的设计和开发工作,期间遇到一些问题和解决方案做些记录。

一、首先没有使用MFC而决定使用Qt是为了跨平台,后续linux和mac项目组只要添加平台相关代码。相关部分使用条件编译区分好即可

二、项目前期工作主要是制定通信协议,关键部分数据采用Json表示,以期达到较高的扩展性

协议的部分,数据类型只要以非平台相关定义即可,使用Byte,char而非int long等跟平台有关的数据。

三、广播模块用于发现服务器和在线人员,这块没什么难点,使用Qt倒是遇到一些问题:

1、在使用Qt 封装的Socket时,Qt程序之间互相收发Socket数据使用QDataStream没有问题,但若是夸平台发送就会遇到问题。
问题就是,各pad端收到的数据包都会多出4Byte数据,以致解析出错,问题的原因我们看看Qt文档:QDataStream的说明
To take one example, a char * string is written as a 32-bit integer equal to the length of the string including the '\0' byte, followed by all the characters of the string including the '\0' byte. When reading a char * string, 4 bytes are read to create the 32-bit length value, then that many characters for the char * string including the '\0' terminator are read.
问题找到之后,只要设计一个类,专门负责数据包转换即可,使用QByteArray。
2、由于各模块做成Qt插件,需要注意 QPluginLoader加载插件时:

If the root component object was destroyed, calling this function creates a new instance.

The root component, returned by this function, is not deleted when the QPluginLoader is destroyed. If you want to ensure that the root component is deleted, you should call unload() as soon you don't need to access the core component anymore. When the library is finally unloaded, the root component will automatically be deleted.

因此导出类,可认为在没有调用unload时是单例模式,不知道这点,会遇到麻烦。

四、鼠标键盘的控制由于需要管理员方式运行,因此独立出去成为一个EXE,主程序以管理员权限运行此exe,并通过QTcpSocket转发

五、文件传输模块设计成独立线程,这样不会阻塞主程序。其次通过文件MD5判断,是否需要重新导出PPT图片

六、PC控制模块负责控制命令的接受和分发处理,同时还需要回复客户端,如PPT翻页了要通知客户端当前索引,以便客户端切换到当前PPT预览图

由于对于QThread线程来说,除了在run函数创建的对象属于当前线程外,只能通过 QObject::moveToThread 来达到同样的效果了。其他的函数和成员都属于主线程。
因此QTcpSocket的创建以及信号槽会放到run函数中完成。但是还是遇到了一个较为棘手的问题:
1、Qt的socket在write完数据之后,如果不调用flush,客户端收到数据包不及时。因此在回复PPT当前页的函数(属于主线程)调用了flush,客户端在快速多次不停上下切页时,服务器崩溃,崩溃地址位于QtCore进行事件转发的地方。一开始不明所以,由于Qt Socket的数据发送也会在下次事件处理完时进行。因此将flush的调用改为qApp->processEvents();解决了崩溃问题,但是Debug版本数据发送还是不及时,而Release版本却可以及时发送。也算是解决了问题

七、PPT控制模块通过MS Office自动化编程完成,主要完成PPT控制,PPT页面导出为jpg,获取PPT备注信息

这块也遇到了一些问题,通过录制PPT宏参考PPT控制代码,发现也有些不正确的,举个例子,从当前页播放PPT录制宏是错误的,其实还是从第一页开始播放。
但我们的需求是要求能从当前页播放PPT,因此做了一些特殊处理:
1、首先隐藏从第一页到当前页的动画效果(否则会播放动画效果卡主切页)
2、开始播放(此时肯定会从第一页开始播放)
3、跳转到当前页码
4、回复第一页到当前页的PPT动画效果

八、主程序界面用QSS进行界面设计贴图,同时要提供二维码界面提供服务器信息

主程序部分会获取当前系统的Ip信息,因此用到了QNetworkInterface相关类,而此类在Windows下如果用QtCreator编译,程序运行会直接崩溃。这类bug在QT相关论坛和官网有人问过,但解决方法不适用。我是通过改用VS进行编译解决的,感觉是因为用到了VS相关的运行时库,而QtCreator配置有误导致的。
获取网卡相关信息这块,由于机器上可能会有多块网卡,还有可能有虚拟网卡这类。因此需要进行过滤,以取到正确的IP信息:
关键部分判断如下:
//由于会取到多个网卡(虚拟),因此对网卡进行过滤
  QNetworkInterface::InterfaceFlags interFlags;
  interFlags = iter->flags();
  if((interFlags & QNetworkInterface::IsUp) &&//网络处于激活状态
 (interFlags & QNetworkInterface::IsRunning) &&//已经分配资源
 (interFlags & QNetworkInterface::CanBroadcast) &&//能进行广播
 (interFlags & QNetworkInterface::CanMulticast) &&//能进行多播
 !(interFlags & QNetworkInterface::IsLoopBack))//非回环地址
  {
    .....
  }

九、广播登录模块,当服务器和客户端夸网段时候(客户端通过上一层路由器连接),广博实效(NAT设备不转发广播包)

解决的办法是通过扫描二维码登录,二维码提供服务器IP和端口号。此情况出现时,客户端的IP地址都会变成路由器地址,因此服务器端识别客户端有两种办法,通过IP+端口,或者通过socket 描述符。

十、当服务器程序运行在笔记本(无线网卡),且笔记本建立WiFi热点,客户端连接WiFi热点,此时的情况是:

默认下服务器IP不变,笔记本共享WiFi地址为192.168.173.1,客户端则为192.168.173.X(即共享的WiFi为客户端的网关)。为了使连接共享WiFi,和同服务器网段客户端

都能连接上次服务器,二维码中要提供原IP+192.168.173.1两个IP,客户端自行解析各IP尝试连接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值