QTcpSocket使用过程中的一些问题记录
目前,在将原来C的socket通讯改为使用Qt类库QTcpSocket通讯,在修改过程中遇到不少问题,在此将问题一并记录,以备后面使用。
采用的通讯方式:QTimer定时器、QThread多线程和QTcpSocket通讯。QTimer设置定时通讯间隔(10s),QThread运行定时器响应函数,QTcpSocket进行数据发送。
1.问题一:QTcpSocket对象创建和使用要在同一个线程,否则报错。
错误描述:QObject:Cannot create children for a parent that is in a different thread.
问题描述:开始是将QTcpSocket对象作为主界面的一个成员变量,因此在构造函数内初始化(new),然后在QThread线程内连接服务端以及进行数据发送。
问题解决:将初始化和连接都放在QThread内,并建立一个长连接,并采用一个标志位表示连接状态,发送前判断连接标志位,以此来进行连接或者发送。
me:连接标志一定要与QTcpSocket的QAbstractSocket::SocketState状态进行关联,可使用信号stateChanged(QAbstractSocket::SocketState)建立连接,在槽函数里修改连接标志
如:
connect(pTcpClientSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,
SLOT(sltStateChanged(QAbstractSocket::SocketState)),Qt::DirectConnection);
.....
void CommTcpClient::sltStateChanged(QAbstractSocket::SocketState state)
{
qDebug()<<"TcpSocketState------"<<state;
switch(state)
{
case QAbstractSocket::ConnectedState:
case QAbstractSocket::ConnectingState:
case QAbstractSocket::ClosingState:
isOpen=true;//isOpen即为连接标志
emit sigCommStateUpdate(state);
break;
case QAbstractSocket::UnconnectedState:
isOpen=false;
emit sigCommStateUpdate(state);
break;
default:
break;
}
}
2.问题二:在QThread内将QTcpSocket对象信号(connected、error、stateChangeed)与槽函数连接报数据类型未注册
错误描述:QObject::connect: Cannot queue arguments of type 'QAbstractSocket::SocketError' (Make sure ‘QAbstractSocket::SocketError' is registered using qRegisterMetaType(). )
问题描述:connect自动连接在线程类中的信号默认是排队模式QueuedConnection,因此需要注册参数类型。
问题解决:方法一,将默认connect的连接方式改为Qt::DirectConnection,就不需要类型信息;方法二,在线程内注册qRegisterMetaType参数类型。
me:不建议采用方法一,治标不治本。采用方法二,具体参考:http://www.cnblogs.com/liushui-sky/p/6422643.html
3.问题三:调用connectToHost建立连接后调用write发送数据失败
错误描述:QNativeSocketEngine::write() was not called in QAbstractSocket::ConnectedState
问题描述:错误为不是在QTcpSocket连接状态下调用write()函数,即调用write()时连接尚未建立
问题解决:方法一,在调用connectToHost后接着调用waitForConnected(timeout),并给延时参数赋值,之后在调用write()函数;
方法二,在信号connected的槽函数里调用write()函数进行数据发送;
方法三,在信号stateChangeed的槽函数内判断当前QTcpSocket对象连接状态state(),如果是QAbstractSocket::ConnectedState则调用write()函数进行数据发送;
实际是使用一个连接标志位来决定是否调用write()函数发送数据,在信号connected的槽函数里修改标志位为真,每次定时器到期都首先判断标志位,为假则重新尝试建立连接。
me:建议方法一方法三结合使用。stateChangeed信号在网线断开的时候有个大概20s的延时,在这20s内socket连接还是在的。这个需要注意。
4.问题四:服务端没开启和网线没连接错误不一样
错误描述:服务端没开启错误为:QTcpSocket Connection Refused,网线没连接错误为:Network operation timed out
问题描述:服务端没开启返回连接被拒绝,网线没连接则会超时,这个可能和网络情况有关系。。。
问题解决:不清楚具体原因,将上述现象作为一个判断区分两者的方法。
5.问题五:连接关闭
错误描述:直接调用disconnect,错误信息忘记了。。。
问题描述:
问题解决:改为调用disconnectFromHost()函数,这个函数会等待这个连接的相关操作(数据发送)完成后才关闭连接。
me:调用完disconnectFromHost函数后,在使用waitFromDisconnected进行等待,跟建立连接时采用的waitForConnected是一个道理。
6.问题六:保活keepalive
错误描述:不发keepalive包
问题描述:对QTcpSocket.socketDescriptor做keepalive配置,在连接成功前配置无效
问题解决:改为在在connected信号槽函数内配置,然后在disconnected信号槽函数内修改连接标志。这样可以监测到对端异常断开的情况,但是本端网线被拔还是监测不到,这是个遗留问题。
me:keepalive还没有试,回头试一下效果,本端网线断开可参考http://www.cnblogs.com/liushui-sky/p/6479510.html,http://www.cnblogs.com/liushui-sky/p/6479466.html监测本地相应网络接口的连接状态。
QNetworkConfigurationManager::onlineStateChanged(),在有多个网络连接(如多个网口、无线等)效果不好,不建议使用。
7.问题七:心跳机制
为了确定连接是否正常,考虑使用两种方法:
方法一:使用问题六中的保活keepalive机制,在空闲时候发送空包,接收对端确认信息,从而确认连接是否正常;
方法二:使用心跳机制,本端定时发送心跳包,然后接收对端回复的心跳包,从而确认连接是否正常;或者在本端发送后接收对端回复的确认信息。
两种方法都是通过数据包来确认连接,相比之下方法一配置简单,不需要修改对端代码,但是两端要进行交互;方法二需要修改服务端代码(在数据接收处增加回复确认信息代码),但是相比方法一少了一次本端向对端发送数据包。(这里本端是指客户端,对端指服务端)
注:me为本人的理解,不当之处还望大家指正。
转自:http://blog.csdn.net/u011430225/article/details/52946332
QTcpSocket使用过程中的一些问题记录的更多相关文章
- linux安装和配置 mysql、redis 过程中遇到的问题记录
linux下部署mysql和redis网上的教程很多,这里记录一下我部署.配置的过程中遇到的一些问题和解决办法. mysql ①安装完成后启动的时候报错 Starting MySQL.The serv ...
- linux安装和配置 mysql、redis 过程中遇到的问题记录(转)
章节目录 mysql redis linux下部署mysql和redis网上的教程很多,这里记录一下我部署.配置的过程中遇到的一些问题和解决办法. mysql ①安装完成后启动的时候报错 Starti ...
- [深度学习][图像处理][毕设][笔记][安装环境][下载地址]安装VS2013、matconvnet、cuda、cudnn过程中产生的一些记录,2018.5.6号
最近半个多月,被cuda等软件折磨的死去活来,昨天下午,终于安装好了环境,趁着matlab正在,在线下载VOT2016数据集,3点睡眼惺忪被闹醒后,睡不着,爬上来写这份记录. 先记录一下自己电脑的基本 ...
- zabbix 3.0.3 (nginx)安装过程中的问题排错记录
特殊注明:安装zabbix 2.4.8和2.4.6遇到2个问题,如下:找了很多解决办法,实在无解,只能换版本,尝试换(2.2.2正常 | 3.0.3正常)都正常,最后决定换3.0.3 1.Error ...
- 我在MySQL免安装版使用过程中遇到的问题记录
我的MySQL版本为:mysql-5.7.16-winx64 安装时间为:2016年5月10号 由于是免安装版,下载好压缩文件之后解压到特定目录下,再打开命令行运行几行命令即可. 在一次操作中,发现无 ...
- Idea 使用过程中遇到的问题记录
1.在Idea启动Tomcat,有时候提示项目启动 failed,请查看日志,此时的日志在Tomcat主目录的日志文件中是没有的,此时的日志记录在: C:\Users\wanhua.lu\.Intel ...
- oracle数据库安装过程中的疑惑—该记录是本人以前写在微博上的文章
转行IT初学者关于oracle数据库整理第一次安装数据库的时候都是按照操作步骤一步一步进行安装,并没有对操作步骤产生过怀疑或者为什么要这么进行操作?2017年12月8日再次阅读安装操作说明书的时候有了 ...
- 使用cocos creator的过程中碰到的问题记录
1>编辑器不能识别脚本里面@property类型,显示为null,脚本拖不上去 是@property的类循环引用导致的,可以改变组件类型到cc.Node解决 2> Cannot read ...
- SVC 工作过程中出现的错误记录(SEO项目)
1.同一のキーを含む項目が既に追加されています.追加的项目中含有重复主键) /seo' アプリケーションでサーバー エラーが発生しました. 同一のキーを含む項目が既に追加されています. 説明: 現在の ...
随机推荐
- 对于在Android Studio 的 build.gradle 中的默认applicationId 要不要写呢?
起因 刚完成一个版本的开发.刚上Google play 就有用户反映无法更新应用.错误代码为:Can't install app "****" can' be installed. ...
- 【Unity】11.7 布料
分类:Unity.C#.VS2015 创建日期:2016-05-02 一.简介 Unity提供了两种布料组件:交互布料(Interactive Cloth).蒙皮布料(Skinned Cloth).为 ...
- 解密DNSPOD应对DDoS攻击招式!
最近,安全专家Incapsula在最新版<DDoS威胁环境报告>指出.现在实施DDoS攻击的人仅仅有两类:一类是专业网络黑客.而还有一类就是所谓的botter. 简言之,booter就是僵 ...
- hdu 2544 最短路(两点间最短路径)
题目:http://acm.hdu.edu.cn/showproblem.php?pid=2544 方法一:dijkstra算法,求两点之间最短路径. /*********************** ...
- Oracle 数据库连接池
jdbc:oracle:thin:@(DESCRIPTION=(failover=on)(enable=broken)(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOS ...
- (原创)发布一个C++版本的ORM库SmartDB(一)
先简单说说ORM的优点: 提高开发效率,减少重复劳动,只和业务实体打交道,由业务实体自动生成sql语句,不用手写sql语句. 简单易用, 可维护性好. 隔离数据源,使得我们更换数据源时不用修改代码. ...
- Content-Type中application/x-www-form-urlencoded 和 multipart/form-data的区别
1.什么是Content-Type Form的enctype属性表示页面表单数据向服务端传输时的编码方式, 常用有两种:application/x-www-form-urlencoded和multip ...
- 设计模式之模板方法模式&&迪米特法则(代码Objective-C展示)
模板方法模式 模板方法模式:定义一个操作中的算法骨架,而将一些步骤延迟到子类中.模板方法使得子类可以在不改变一个算法的结构即可重定义该算法的某些特定步骤. 比如说,小时候数学老师的随堂检测,都是在黑板 ...
- cf 366D D. Dima and Trap Graph (计算所有线段共同覆盖的某段区间)
http://codeforces.com/problemset/problem/366/D 题意:给出n个点,m条边,a,b,ll,rr分别代表点a,点b相连,点a和点b的区间范围(ll,rr),然 ...
- Spring事务管理要点总结
# Spring事务管理要点总结 ### 要点---- 事务是企业级应用中必不可缺少的技术,用来确保数据的完整性和一致性.- Spring事务管理并不实现事务管理的实现,而是借助Hibernate\J ...