Qt网络多线程中,readyRead无法多次触发

[复制链接]
查看11 | 回复4 | 2021-1-27 06:47:43 | 显示全部楼层 |阅读模式
现在需要在主机端(windows)连接多个客户端(linux),子类了一个QObect如下:
classHandlerClients:publicQObject{
Q_OBJECT
public:
HandlerClients::HandlerClients(intsockDescriptor)
:QObject()
{
m_sockDescriptor=sockDescriptor;
m_socket=newQTcpSocket(this);
m_socket->setSocketDescriptor(m_sockDescriptor);
connect(m_socket,SIGNAL(readyRead()),this,SLOT(clientReadyRead()));
connect(m_socket,SIGNAL(disconnected()),this,SLOT(clientDisconnected()));
}
}
classHandlerClients::clientReadyRead()
{
/*reveivebytesfromclients*/
}
然后每次有新的客户端连接时就会在子类的QServer的incomingConnection中new一个新的client,并丢到新的线程中,大体代码如
下:
voidNetServer::incomingConnection(intsockDesp)
{
QThread*thread=newQThread();
HandlerClients*client=newHandlerClients(sockDescriptor);
connect(thread,SIGNAL(finished()),client,SLOT(deleteLater()));
client->moveToThread(thread);
thread->start();
}
现在碰到的问题是,当某个客户端发第一个包时,readyRead可以被正常触发并接收数据;但是发第二个包时,readyRead没有被触发,但是客户
端显示数据已经发送出去了。本人对Qt的多线程应用比较菜,请问各位问题可能出在哪?
分 -->
回复

使用道具 举报

千问 | 2021-1-27 06:47:43 | 显示全部楼层
直接把HandlerClients改成继承自QThread不行吗?另外,我没有看到线程执行exec()方法,也就是说线程没有启动自己的事件循环,原则上是不能处理信号和槽的。
还有,如果没有特别的要求,你完全可以在线程中使用阻塞式的通讯方式,即使用类似waitForReadyRead的方法
回复

使用道具 举报

千问 | 2021-1-27 06:47:43 | 显示全部楼层
引用1楼xiachm的回复:直接把HandlerClients改成继承自QThread不行吗?另外,我没有看到线程执行exec()方法,也就是说线程没有启动自己的事件循环,原则上是不能处理信号和槽的。
还有,如果没有特别的要求,你完全可以在线程中使用阻塞式的通讯方式,即使用类似waitForReadyRead的方法

我原来就是使用的就是您说的这种方法,子类QThread并在其run()中执行exec(),但是通过线程发送数据时(调用socket的write()成员函数)会报cannotcreatechildrenforaparentthatisinadifferentthread.在网上查了些资料后,所以后来就改成了这种方法。
我有个地方不明白的是为什么当客户端第一次发包过来的时候,信号和槽可以正常触法执行,而当第二次发包时,readyRead()就不能被触法了?
回复

使用道具 举报

千问 | 2021-1-27 06:47:43 | 显示全部楼层
引用2楼king_gang的回复:我原来就是使用的就是您说的这种方法,子类QThread并在其run()中执行exec(),但是通过线程发送数据时(调用socket的write()成员函数)会报cannotcreatechildrenforaparentthatisinadifferentthread.在网上查了些资料后,所以后来就改成了这种方法。
是信号和槽的连接方式不对,把connect的最后一个参数,也就是ConnectionType,改成Qt::DirectConnection就可以了。
还是我说的那句老话,楼主为什么要用信号和槽呢?使用阻塞式的写法会更加简单。
回复

使用道具 举报

千问 | 2021-1-27 06:47:43 | 显示全部楼层
引用3楼xiachm的回复:Quote: 引用2楼king_gang的回复:
我原来就是使用的就是您说的这种方法,子类QThread并在其run()中执行exec(),但是通过线程发送数据时(调用socket的write()成员函数)会报cannotcreatechildrenforaparentthatisinadifferentthread.在网上查了些资料后,所以后来就改成了这种方法。

是信号和槽的连接方式不对,把connect的最后一个参数,也就是ConnectionType,改成Qt::DirectConnection就可以了。
还是我说的那句老话,楼主为什么要用信号和槽呢?使用阻塞式的写法会更加简单。

啊?还真有这么多和我一样遇到这个问题的,我也是这样,真的请赐教,你们是怎么解决的,能给下具体放啊嘛?我贴上我自己的一点代码voidQTcpSocketThread::run()
{
tcpSocket=newQTcpSocket();
Q_ASSERT(tcpSocket);
if(!tcpSocket->setSocketDescriptor(socketDescriptor))
{
emiterror(tcpSocket->error());
return;
}
connect(tcpSocket,
SIGNAL(readyRead()),
this,
SLOT(socketRead()),
Qt::DirectConnection);
connect(tcpSocket,
SIGNAL(disconnected()),
this,
SLOT(socketDisconnect()));
exec();
}
voidQTcpSocketThread::socketRead()
{
recvPkgBuffer=tcpSocket->readAll();
qDebug()
大家也看到了,这是我最初的代码,服务器发送命令,接收到返回的数据后解析,然后发送下一条,然后接收解析,以此类推。后来我改进了代码,发送一条指令,然后传感器间隔一秒陆续返回,但是只接收到第一条,再也显示不出来,也不知道是接收还是没收到,qDebug()反正没显示,真的困扰的我这些日子睡不着,你们是怎么解决的,有没有别的途径,阻塞式的写法是什么???
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行