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

ezhong0812 2013-10-16 01:02:00
对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
...全文
354 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
ezhong0812 2013-10-21
  • 打赏
  • 举报
回复
引用 12 楼 LazyDreamHunter 的回复:
楼主,信号槽机制用法的问题,建议改用非信号槽机制
能有详细点的介绍或者连接吗?非常感谢。 现在服务器也用QTcpServer /QTcpSocket改写了,不会出现65536/65532(65532是因为我前面有4字节包大小预留)的问题。 但是在线程中创建QTcpSocket的时候还是会有 QObject: Cannot create children for a parent that is in a different thread.这种问题。
RabinSong 2013-10-18
  • 打赏
  • 举报
回复
楼主,信号槽机制用法的问题,建议改用非信号槽机制
  • 打赏
  • 举报
回复
(Parent is QTcpSocket(0x721548), parent's thread is NTcpThread(0x70f218), current thread is QThread(0x696c50) 父对象的线程是NTcpThread,而你的TcpSocket是在QThread(目测主线程)里面构造的
ezhong0812 2013-10-17
  • 打赏
  • 举报
回复
引用 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构造的都有问题。[/quote] 这个提示让我很郁闷,因为我只有一个QTcpSocket对象是在线程run函数中创建,而且提示是Parent is QTcpSocket,这就更郁闷了,QTcpSocket的子类对象应该是QT库的东西,也不是我来创建。
  • 打赏
  • 举报
回复
引用 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构造的都有问题。
ezhong0812 2013-10-17
  • 打赏
  • 举报
回复
服务器是用boost::asio写的...客户端是用QT写 做了些小的例子测试,有可能是服务器导致的 但之前客户端和服务器都是boost::asio写的时候,没有出过问题。
ezhong0812 2013-10-17
  • 打赏
  • 举报
回复
引用 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; …… }
dragon_dev 2013-10-16
  • 打赏
  • 举报
回复
dragon_dev 2013-10-16
  • 打赏
  • 举报
回复
先看看,等候解决。
ezhong0812 2013-10-16
  • 打赏
  • 举报
回复
来个人解决下啊
u010808838 2013-10-16
  • 打赏
  • 举报
回复
顶一个,神一样的存在!
liucheng8789 2013-10-16
  • 打赏
  • 举报
回复
走起!顶一个
ezhong0812 2013-10-16
  • 打赏
  • 举报
回复
运行的时候开始会提示: 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)

16,240

社区成员

发帖
与我相关
我的任务
社区描述
Qt 是一个跨平台应用程序框架。通过使用 Qt,您可以一次性开发应用程序和用户界面,然后将其部署到多个桌面和嵌入式操作系统,而无需重复编写源代码。
社区管理员
  • Qt
  • 亭台六七座
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧