多线程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) --------------------编程问答-------------------- 走起!顶一个 --------------------编程问答-------------------- 顶一个,神一样的存在! --------------------编程问答--------------------
来个人解决下啊 --------------------编程问答-------------------- 先看看,等候解决。 --------------------编程问答-------------------- --------------------编程问答--------------------
代码太长了,我没看,只看了这一段。父对象和子对象要在一个线程里。目测这三个几个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(目测主线程)里面构造的 --------------------编程问答--------------------
(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写的时候,没有出过问题。
--------------------编程问答-------------------- 楼主,信号槽机制用法的问题,建议改用非信号槽机制 --------------------编程问答--------------------
楼主,信号槽机制用法的问题,建议改用非信号槽机制
能有详细点的介绍或者连接吗?非常感谢。
现在服务器也用QTcpServer /QTcpSocket改写了,不会出现65536/65532(65532是因为我前面有4字节包大小预留)的问题。
但是在线程中创建QTcpSocket的时候还是会有 QObject: Cannot create children for a parent that is in a different thread.这种问题。
补充:移动开发 , Qt