• QT多线程中使用QTcpSocket遇到的读写数据问题


    多线程中使用QTcpSocket
    在run()方法中new QTcpSocket;然后监听readyRead()信号connect(m_pTcpSocket,SIGNAL(readyRead()),this,SLOT(sloat_RecvData()));

    问题是当需要给服务器发送一段命令时(使用m_pTcpSocket->write(byteArray);)程序会报出警告QSocketNotifier: socket notifiers cannot be enabled from another thread
    我在QThread的子类WorkerThread中使用QTcpSocket来连接TCP服务器并给服务器发送数据。
    void WorkerThread::run()
    {
      m_pTcpSocket = new QTcpSocket();
      while (1) {
        …;
        m_pTcpSocket->connectToHost(QHostAddress::LocalHost, 8001);  // 连接服务器
        m_pTcpSocket->waitForConnected(3000);              // 等待确保连接成功
        int nByteWrite = m_pTcpSocket->write(strMessage.toUtf8());                 // 发送数据到服务器 
      }
    }
    可以连接到服务器,但是调用write发送数据时,服务端一直接收不到,表示这里发送失败了,客户端发不出数据了~
    解决
    后来在使用完write()方法后,再使用flush()方法,就可以发送消息了。
    qt的官方文档里说,调用了flush()方法后,可以把缓冲的数据立刻发送出去。
    估计QTcpSocket中的write()方法是带有缓冲的。
    void WorkerThread::run()
    {
      m_pTcpSocket = new QTcpSocket();
      while (1) {
        …;
        m_pTcpSocket->connectToHost(QHostAddress::LocalHost, 8001);
        m_pTcpSocket->waitForConnected(3000);
        int nByteWrite = m_pTcpSocket->write(strMessage.toUtf8());
        m_pTcpSocket->flush();
      }
    }

    上面的客户端TcpSocket成功地将数据write发送给了服务端,但是又发现客户端readyRead信号一直不进它的槽函数sloat_RecvData()。真是一波刚平一波又起啊,现在客户端又收不到数据了~
    解决
    检查connect(tcpSocket, SIGNAL(readyRead()),this,SLOT(update_message()));返回值为true,说明信号槽连接起来了~
    服务端检查write函数的返回值,为非零,说明也发出去了~
    线程while(1)循环很快,在该循环中,循环过快,导致connect来不及处理数据,所以使用waitForReadyRead()将循环进行阻塞,当有数据读入时取消阻塞,进入下一轮循环。
    void WorkerThread::run()
    {
      m_pTcpSocket = new QTcpSocket();
      while (1) {
        …;
        m_pTcpSocket->connectToHost(QHostAddress::LocalHost, 8001);
        m_pTcpSocket->waitForConnected(3000);
        int nByteWrite = m_pTcpSocket->write(strMessage.toUtf8());
        m_pTcpSocket->flush();
        m_pSocket->waitForReadyRead();
      }
    }

    在多线程中是socket,确实挺棘手的!记录一下,仅供参考~

  • 相关阅读:
    Socket编程实现客户端与服务器一对一聊天
    HttpClient获取页面信息与Jsoup封装获取
    代码推送
    re正则
    MySQL 的主从复制
    关于前后端的缓存
    session/cookie/token
    如何保证缓存(redis)与数据库(MySQL)的一致性
    进程与线程(程序与任务)
    QA/QC
  • 原文地址:https://www.cnblogs.com/MakeView660/p/10938075.html
Copyright © 2020-2023  润新知