zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    SpringMVC + MyBatis简单示例
    JSP---JSTL核心标签库的使用
    HBASE安装 (HA)
    HBase 常用Shell命令(转载)
    kafka quick start
    在IDEA中实战Git
    kibana6.2.2安装
    elasticsearch-head插件安装
    elasticsearch6.2.2安装
    jdk1.8安装
  • 原文地址:https://www.cnblogs.com/liushui-sky/p/6490810.html
Copyright © 2011-2022 走看看