[英]QTcpSocket: message not send from another thread
我知道这个主题已经有很多话题了,但是没人能纠正我的问题。我希望有人能找到解决方案。
主题:我正在开发多线程游戏服务器。 然后,我重载了TcpServer来写我的等等。
void TcpServerCustomersHandler::incomingConnection(qintptr socketDescriptor)
{
ThreadCustomer* client = new ThreadCustomer(socketDescriptor);
connect(client, &ThreadCustomer::finished, client, &ThreadCustomer::deleteLater);
client->start();
}
我编写了另一个使QThread重载的类并编写了我的连接。 在“问题/答案”模式下,它起作用。 我收到消息并回复。
void ThreadCustomer::run()
{
qDebug() << "Starting thread: " << m_socketDescriptor;
m_tcpSocket = new QTcpSocket();
if(!m_tcpSocket->setSocketDescriptor(m_socketDescriptor))
{
qCritical() << "Error creation thread:" << m_tcpSocket->errorString();
return;
}
connect(m_tcpSocket, &QTcpSocket::readyRead, this, &ThreadCustomer::onReadyRead_TcpSocket, Qt::DirectConnection);
connect(m_tcpSocket, &QTcpSocket::disconnected, this, &ThreadCustomer::onDisconnected_TcpSocket, Qt::DirectConnection);
connect(InstanceManager::instance(), &InstanceManager::readyRead, this, &ThreadCustomer::onReadyRead_InstanceManager);
exec();
}
void ThreadCustomer::onReadyRead_TcpSocket()
{
QByteArray message = m_tcpSocket->readAll();
//works...
m_tcpSocket->write(message);
}
但是,由于它是一个游戏服务器,我希望他能够发送“通知”。 这意味着向玩家发送消息之前不会收到任何消息。 这些通知由单例“ InstanceManager”发送。
void ThreadCustomer::onReadyRead_InstanceManager(QByteArray message)
{
m_tcpSocket->write(message);
}
这是我的问题。 当调用“ write()”时,没有消息发出,并且我有一条著名的消息:“ QSocketNotifier:无法从另一个线程启用或禁用套接字通知程序”。 我知道我有此消息,因为尽管有连接,但还是从另一个线程中调用了“ write()”。
不幸的是,我找不到解决该问题的解决方案。 有人有主意吗?
好的,感谢@wtom,我找到了第一个基于队列的解决方案。
我在我的QThread中使用QTimer来处理消息并避免冲突。 为他人:
void ThreadCustomer::run()
{
qDebug() << "Starting thread: " << m_socketDescriptor;
m_tcpSocket = new QTcpSocket();
if(!m_tcpSocket->setSocketDescriptor(m_socketDescriptor))
{
qCritical() << "Error creation thread:" << m_tcpSocket->errorString();
return;
}
m_timerWritting = new QTimer();
connect(m_timerWritting, &QTimer::timeout, this, &ThreadClient::onTimeOut_timerWritting, Qt::DirectConnection);
m_timerWritting->start(500);
connect(m_tcpSocket, &QTcpSocket::readyRead, this, &ThreadClient::onReadyRead_TcpSocket, Qt::DirectConnection);
connect(m_tcpSocket, &QTcpSocket::disconnected, this, &ThreadClient::onDisconnected_TcpSocket, Qt::DirectConnection);
connect(InstanceManager::instance(), &InstanceManager::readyRead, this, &ThreadClient::onReadyRead_InstanceManager, Qt::QueuedConnection);
exec();
}
void ThreadCustomer::onReadyRead_InstanceManager(QByteArray message)
{
m_listMessageToSend.append(message);
}
void ThreadCustomer::onTimeOut_timerWritting()
{
if(m_listMessageToSend.count() > 0)
{
QByteArray message = m_listMessageToSend.takeFirst();
m_tcpSocket->write(message);
}
}
我不知道这是否是更好的解决方案,但是可行:)
我不完全记得它是如何完成的,因此它是更多的伪代码,但关键是当您将InstanceManager :: readyRead连接到ThreadCustomer :: onReadyRead_InstanceManager (在就绪读取事件上写入-是否要这样做 ?), ThreadCustomer :: onReadyRead_InstanceManager将在创建ThreadCustomer的线程中执行,该线程执行void TcpServerCustomersHandler :: incomingConnection(qintptr socketDescriptor) 。 这不是您想要的。 您必须将ThreadCustomer的 线程关联 更改为执行ThreadCustomer :: run()的线程
编辑 ThreadCustomer是从QThread派生的,对吗?
void TcpServerCustomersHandler::incomingConnection(qintptr socketDescriptor)
{
ThreadCustomer* client = new ThreadCustomer(socketDescriptor);
client->moveToThread(&client); // in canonical way QThread and ThreadCustomer are different objects: client->moveToThread(&thread);, but may be it will work like this?
connect(client, &ThreadCustomer::finished, client, &ThreadCustomer::deleteLater);
client->start();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.