Здравствуйте!
Проблема следующая: есть написанный и отлаженный клиент, а есть сервер, у которого проблемы с многопоточностью ибо все моих рук дело.
Что хочется: чтобы каждый клиент обрабатывался в QThread::run().
В чем проблема:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QLocalSocket(0x758fa8), parent's thread is QThread(0x8216b0), current
thread is NewConnectionThread(0x7581f8)
Код run-a:
void NewConnectionThread::run()
{
clientSocket =
parentLocalServerRef->getServerRef()->nextPendingConnection();
// connect(clientSocket, SIGNAL(readyRead()), this, SLOT(read()));
while (clientSocket->bytesAvailable() < (int)sizeof(quint32)) {
clientSocket->waitForReadyRead(1);
}
connect(clientSocket, SIGNAL(disconnected()),
clientSocket, SLOT(deleteLater()));
QByteArray newClientName = clientSocket->peek(30);
qDebug() << " New client name : " << newClientName << "\n";
QString currentDate = parentLocalServerRef->getCurrentDate();
qDebug() << " Sending to " << newClientName
<< " current date : " << currentDate << "\n";
QByteArray response = currentDate.toLatin1();
clientSocket->write(response);
clientSocket->flush();
qDebug() << " Finish sending. Close the Thread.";
stopProcess = true;
//while (!stopProcess) {}
}
Причину, кажется, понимаю: clientSocket->write(response) рискует просуществовать дольше своего потока. Но при этом не очень понимаю, как исправить без костылей.
Еще есть второй момент, в clientSocket->waitForReadyRead(1). Судя по докам, когда данные готовы к чтению, он не дожидаясь дефолтного счетчика (30000 мс) возвращает готовность. Но не тут-то было и в этой вариации оно ждет полностью счетчик. В абсолютно таком же run-e, разве-что в реализации с гуи (вешепредставленны ран из консоли, но мне кажется это не должно влиять на выполнение метода Оо), оно сразу выходит из ожидания. ЧЯДНТ?
Немного подумав, я вспомнил, что клиент читал малость по-другому и ожидал через сигнал readReady(). Ну, ладно, делаем, объявляю слот read() у потока и в итоге:
NewConnectionThread::NewConnectionThread(LocalServer* parentLocalServerRef,
QObject *parent) :
QThread(parent),
parentLocalServerRef(parentLocalServerRef)
{
stopProcess = false;
}
void NewConnectionThread::run()
{
clientSocket =
parentLocalServerRef->getServerRef()->nextPendingConnection();
connect(clientSocket, SIGNAL(readyRead()), this, SLOT(read()));
//while (!stopProcess) {}
}
void NewConnectionThread::read()
{
connect(clientSocket, SIGNAL(disconnected()),
clientSocket, SLOT(deleteLater()));
QByteArray newClientName = clientSocket->peek(30);
qDebug() << " New client name : " << newClientName << "\n";
QString currentDate = parentLocalServerRef->getCurrentDate();
qDebug() << " Sending to " << newClientName
<< " current date : " << currentDate << "\n";
QByteArray response = currentDate.toLatin1();
clientSocket->write(response);
clientSocket->flush();
qDebug() << " Finish sending. Close the Thread.";
stopProcess = true;
}
Казалось бы, все распрекрасно, и ошибок нет и читает быстро. Вот только многопоточности почему-то нету... Т.е., нету ее потому что run() заканчивается после коннекта? И потом read() выполняется в основном потоке, как я понял, судя по дебагу (там всегда 1 поток был на обработку клиента, менялся только айдишник).
Ниже, весь код сервера:
_________localserver.h
#ifndef LOCALSERVER_H
#define LOCALSERVER_H
#include <QObject>
#include <QString>
#include <QLocalServer>
#include <QMutex>
#include <QDateTime>
class LocalServer : public QObject
{
Q_OBJECT
QString pipeName;
QLocalServer* localServer;
QDateTime currentDate;
QMutex mutex;
public:
explicit LocalServer(QString pipeName = "pipeJAkutenshi",
QObject *parent = 0);
QLocalServer *getServerRef();
QString getCurrentDate();
signals:
public slots:
void newLocalSocketConnection();
};
#endif // LOCALSERVER_H
_______localserver.cpp
#include "localserver.h"
#include "newconnectionthread.h"
LocalServer::LocalServer(QString pipeName, QObject *parent) :
QObject(parent), pipeName(pipeName)
{
localServer = new QLocalServer();
localServer->listen(pipeName);
qDebug() << "Server pipe" << pipeName
<< "is started and waiting for new clients...\n";
connect(localServer, SIGNAL(newConnection()),
this, SLOT(newLocalSocketConnection()));
}
QLocalServer *LocalServer::getServerRef() { return localServer; }
QString LocalServer::getCurrentDate()
{
mutex.lock();
currentDate = QDateTime::currentDateTime();
QString stringCurrentDate =
currentDate.toString("dd.MM.yyyy hh:mm:ss");
mutex.unlock();
return stringCurrentDate;
}
void LocalServer::newLocalSocketConnection()
{
qDebug() << "New client!\n";
NewConnectionThread* newClientConnection =
new NewConnectionThread(this);
newClientConnection->start();
qDebug() << "Server is created new Thread and waiting for new clients...\n";
}
_________newconnectionthread.h
#ifndef NEWCONNECTIONTHREAD_H
#define NEWCONNECTIONTHREAD_H
#include <QThread>
#include "localserver.h"
class NewConnectionThread : public QThread
{
Q_OBJECT
QLocalSocket* clientSocket;
bool stopProcess;
public:
explicit NewConnectionThread(LocalServer* parentLocalServerRef,
QObject *parent = 0);
void run();
LocalServer* parentLocalServerRef;
signals:
public slots:
void read();
};
#endif // NEWCONNECTIONTHREAD_H
_________newconnectionthread.cpp
NewConnectionThread::NewConnectionThread(LocalServer* parentLocalServerRef,
QObject *parent) :
QThread(parent),
parentLocalServerRef(parentLocalServerRef)
{
stopProcess = false;
}
void NewConnectionThread::run()
{
clientSocket =
parentLocalServerRef->getServerRef()->nextPendingConnection();
connect(clientSocket, SIGNAL(readyRead()), this, SLOT(read()));
//while (!stopProcess) {}
}
void NewConnectionThread::read()
{
connect(clientSocket, SIGNAL(disconnected()),
clientSocket, SLOT(deleteLater()));
QByteArray newClientName = clientSocket->peek(30);
qDebug() << " New client name : " << newClientName << "\n";
QString currentDate = parentLocalServerRef->getCurrentDate();
qDebug() << " Sending to " << newClientName
<< " current date : " << currentDate << "\n";
QByteArray response = currentDate.toLatin1();
clientSocket->write(response);
clientSocket->flush();
qDebug() << " Finish sending. Close the Thread.";
stopProcess = true;
}
_________main.cpp
#include <QCoreApplication>
#include "localserver.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
LocalServer* server =
new LocalServer();
return a.exec();
}
Слезливо прошу о помощи, ибо дедлайн буквально завтра, впереди корба и соап, а на пайпы я потратил по таким мелочам больше 2х ночей и моральных сил сделать нормально без костылей уже нету.
Спасибо!