[英]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.