当前位置:编程学习 > wap >>

多线程QTcpSocket 收数据到65532字节时停止

对QTcpSocket进行封装,想要实现,调用端异步读指定bytes数的数据,也就是调用端读100字节,当封装读到100字节时,给调用端一个signal.
问题:随机出现读到65532字节的时候不再收到readyRead信号。
服务器发送的数据一般在700KB左右。假如发送40个这样的数据包,客户端(也就是找个封装)会随机卡在一个包上,最后一个readyRead信号显示有65532个字节收到.

代码如下:

#include "NTcpThread.h"
#include <assert.h>

NTcpThread::NTcpThread(QObject *parent)
    : QThread(parent),
      pSock_(0
          //new QTcpSocket
          ),
      pendingRead_(false),
      bytesToRead_(0), bytesReaded_(0), bufRead_(0),
      pendingWrite_(false),
      bytesToWrite_(0), bytesWritten_(0), bufWrite_(0)
{
    //pSock_->moveToThread(this);

//    connect(pSock_, SIGNAL(connected()), SIGNAL(onConnected())
//            //,Qt::QueuedConnection
//            );

//    connect(pSock_, SIGNAL(disconnected()), SLOT(socketDisconnected())
//            // ,Qt::QueuedConnection
//            );

//    connect(pSock_, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
//            SLOT(socketStateChanged(QAbstractSocket::SocketState))
//            //,Qt::QueuedConnection
//            );

//    connect(pSock_, SIGNAL(error(QAbstractSocket::SocketError)),
//            SLOT(socketError(QAbstractSocket::SocketError))
//            //,Qt::QueuedConnection
//            );

//    connect(pSock_, SIGNAL(readyRead()), SLOT(socketReadyRead())
//            //,Qt::QueuedConnection
//            );

//    connect(pSock_, SIGNAL(bytesWritten(qint64)), SLOT(socketBytesWritten(qint64))
//            //,Qt::QueuedConnection
//            );
}
NTcpThread::~NTcpThread()
{
    delete pSock_;
}
void NTcpThread::run()
{
    qDebug()<<"NTcpThread::run() ,thread id is "<<currentThread()<<"\n";
    QTcpSocket *pSock = new QTcpSocket;

    connect(pSock, SIGNAL(connected()), SIGNAL(onConnected())
            ,Qt::QueuedConnection
            );

    connect(pSock, SIGNAL(disconnected()), SLOT(socketDisconnected())
            // ,Qt::QueuedConnection
            );

    connect(pSock, SIGNAL(stateChanged(QAbstractSocket::SocketState)),
            SLOT(socketStateChanged(QAbstractSocket::SocketState))
            //,Qt::QueuedConnection
            );

    connect(pSock, SIGNAL(error(QAbstractSocket::SocketError)),
            SLOT(socketError(QAbstractSocket::SocketError))
            //,Qt::QueuedConnection
            );

    connect(pSock, SIGNAL(readyRead()), SLOT(socketReadyRead())
            //,Qt::QueuedConnection
            );

    connect(pSock, SIGNAL(bytesWritten(qint64)), SLOT(socketBytesWritten(qint64))
            //,Qt::QueuedConnection
            );

    pSock_ = pSock;

    initCond_.wakeOne();

    //讲此函数设置成同步函数..
    while(true){
        QMutexLocker locker(&readLock_);
        readCond_.wait(&readLock_);

        pSock_->read(bufRead_,bytesToRead_);
        emit onReadCompleted();
        pendingRead_ = false;
        bufRead_ = 0;
        bytesToRead_ = 0;
       // msleep(1);
    }

    qDebug()<<"NTcpThread::run()\n";

}

void NTcpThread::asyncConnect(const QString &hostName, quint16 port)
{
    pSock_->connectToHost(hostName, port, QIODevice::ReadWrite);
}
bool NTcpThread::blockingConnect(const QString &hostName, quint16 port, int msecs)
{
    QMutexLocker locker(&initLock_);
    initCond_.wait(&initLock_);
    pSock_->connectToHost(hostName, port, QIODevice::ReadWrite);
    return pSock_->waitForConnected(msecs);
}

bool NTcpThread::pendingRead()
{
    QMutexLocker lock(&pendingReadLock_);
    return pendingRead_;
}
void NTcpThread::pendingRead(bool pending)
{
    QMutexLocker lock(&pendingReadLock_);
    pendingRead_ = pending;
}

void NTcpThread::asyncRead(quint64 bytesToRead, char *buf)
{
    QMutexLocker locker(&readLock_);
    bufRead_ = buf;
    bytesToRead_ = bytesToRead;
    pendingRead_ = true;
    qDebug() << "NTcpThread::asyncRead, bytesAvailable()" << pSock_->bytesAvailable() << "bytesToRead_" << bytesToRead_;
    if (pSock_->bytesAvailable() >= bytesToRead_)
        readCond_.wakeAll();
}
//如果不使用线程处理,socketReadyRead在主线程中调用
void NTcpThread::socketReadyRead()
{
    QMutexLocker locker(&readLock_);
    qDebug() << "NTcpThread::socketReadyRead: " << pSock_->bytesAvailable();
    if(pendingRead_)
        if (pSock_->bytesAvailable() >= bytesToRead_)
            readCond_.wakeAll();
}

void NTcpThread::asyncWrite(quint64 bytesToWrite, char const *buf)
{
    assert( !pendingWrite_ );//上一个写请求未完成时,不能再写了
    pendingWrite_ = true;
    bytesWritten_ = 0;
    bytesToWrite_ = bytesToWrite;
    bufWrite_ = buf;
    pSock_->write(buf, bytesToWrite);
    pSock_->waitForBytesWritten();
    if( bytesWritten_ == (quint64)-1 )
        assert(0);
}
void NTcpThread::socketBytesWritten(qint64 bytesWritten)
{
    qDebug() << "written " << bytesWritten << "bytes\n";

    if( !pendingWrite_ )
        return;

    if( bytesWritten + bytesWritten_ == bytesToWrite_ )
    {
        pendingWrite_ = false;
        bytesWritten_ = 0;
        emit onWriteCompleted();
        return;
    }

    bytesWritten_ += bytesWritten;
    pSock_->write(bufWrite_ + bytesWritten_, bytesToWrite_ - bytesWritten_);
}

void NTcpThread::socketDisconnected()
{

}

void NTcpThread::socketError(QAbstractSocket::SocketError socketError)
{
    qDebug()<<"NTcpThread::socketError "<<pSock_->errorString()<<"\n";
    Q_UNUSED(socketError);
}

void NTcpThread::socketStateChanged(QAbstractSocket::SocketState socketState)
{
    Q_UNUSED(socketState);
}




大体思路是:
一个单独的线程循环中等待条件A,条件A使能时将数据读到指定缓冲中,给调用者发送读OK信号。
QTcpSocket的signal在主线程中回应,判断是否数据达到要读的个数,数据够时使能条件A
QTcpSocket QThread 65532 --------------------编程问答-------------------- 运行的时候开始会提示:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0x721548), parent's thread is NTcpThread(0x70f218), current thread is QThread(0x696c50)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0x721548), parent's thread is NTcpThread(0x70f218), current thread is QThread(0x696c50)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0x721548), parent's thread is NTcpThread(0x70f218), current thread is QThread(0x696c50) --------------------编程问答-------------------- 走起!顶一个 --------------------编程问答-------------------- 顶一个,神一样的存在! --------------------编程问答--------------------
来个人解决下啊 --------------------编程问答-------------------- 先看看,等候解决。 --------------------编程问答-------------------- --------------------编程问答--------------------
引用 1 楼 ezhong0812 的回复:
运行的时候开始会提示:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0x721548), parent's thread is NTcpThread(0x70f218), current thread is QThread(0x696c50)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0x721548), parent's thread is NTcpThread(0x70f218), current thread is QThread(0x696c50)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0x721548), parent's thread is NTcpThread(0x70f218), current thread is QThread(0x696c50)

代码太长了,我没看,只看了这一段。父对象和子对象要在一个线程里。目测这三个几个QTcpSocket构造的都有问题。 --------------------编程问答--------------------
引用 7 楼 HeadmasterWang 的回复:
Quote: 引用 1 楼 ezhong0812 的回复:

运行的时候开始会提示:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0x721548), parent's thread is NTcpThread(0x70f218), current thread is QThread(0x696c50)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0x721548), parent's thread is NTcpThread(0x70f218), current thread is QThread(0x696c50)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0x721548), parent's thread is NTcpThread(0x70f218), current thread is QThread(0x696c50)

代码太长了,我没看,只看了这一段。父对象和子对象要在一个线程里。目测这三个几个QTcpSocket构造的都有问题。


这个提示让我很郁闷,因为我只有一个QTcpSocket对象是在线程run函数中创建,而且提示是Parent is QTcpSocket,这就更郁闷了,QTcpSocket的子类对象应该是QT库的东西,也不是我来创建。 --------------------编程问答-------------------- (Parent is QTcpSocket(0x721548), parent's thread is NTcpThread(0x70f218), current thread is QThread(0x696c50)
父对象的线程是NTcpThread,而你的TcpSocket是在QThread(目测主线程)里面构造的 --------------------编程问答--------------------
引用 9 楼 HeadmasterWang 的回复:
(Parent is QTcpSocket(0x721548), parent's thread is NTcpThread(0x70f218), current thread is QThread(0x696c50)
父对象的线程是NTcpThread,而你的TcpSocket是在QThread(目测主线程)里面构造的


QTcpSocket对象是在NTcpThread线程里构建的 
void NTcpThread::run() {     
    QTcpSocket *pSock = new QTcpSocket; 
……
}
--------------------编程问答-------------------- 服务器是用boost::asio写的...客户端是用QT写
做了些小的例子测试,有可能是服务器导致的
但之前客户端和服务器都是boost::asio写的时候,没有出过问题。
--------------------编程问答-------------------- 楼主,信号槽机制用法的问题,建议改用非信号槽机制 --------------------编程问答--------------------
引用 12 楼 LazyDreamHunter 的回复:
楼主,信号槽机制用法的问题,建议改用非信号槽机制


能有详细点的介绍或者连接吗?非常感谢。

现在服务器也用QTcpServer /QTcpSocket改写了,不会出现65536/65532(65532是因为我前面有4字节包大小预留)的问题。

但是在线程中创建QTcpSocket的时候还是会有 QObject: Cannot create children for a parent that is in a different thread.这种问题。
补充:移动开发 ,  Qt
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,