ich sitze gerade vor meinem Code und frage mich, ob das so im Langzeitbetrieb funktionieren kann. Zunächst ein wenig Text um alles zu erklären:
Ich programmiere gerade einen kleinen Server auf dem der User sich einloggen muss.
Als erstes wird ein Serverobjekt generiert, dass ein von QTCPServer abgeleitetes Objekt enthält. ( Dieses Objekt hat auch die QList und QHash die ich später noch erwähne )
Sobald eine neue Verbindung erstellt wurde wird ein neues Objekt ( MyClient ) erstellt, das auch ein QTCPSocket enthält und indessen dann der Socketdescriptor geschrieben wird. Dann wird in ein QList der Pointer auf das MyClient-Objekt geschrieben ( falls der Server von sich aus mal Daten an den Client schicken will ) ( Wenn der User sich dann einloggt, wird der Pointer in ein QHash mit dem entsprechenden Usernamen geschrieben und in QList gelöscht ).
Wenn der Client etwas sendet, übermittelt er zuerst die Anzahl an Bytes ( nextBlockSize ) und sendet dann Daten. Sobald bytesAvailable die Größe von
nextBlockSize erreicht hat, werden die verfügbaren Daten ausgelesen und ein Thread in den Threadpool geworfen, der dann die Auswertung der Daten übernimmt ( wenn er
damit fertig ist und eine Antwort senden will, sendet der Thread im Threadpool ein Signal mit dem zu sendenden QByteArray an das MyClient-Objekt ). Klappt auch alles
wunderbar. Jetzt wird die Verbindung irgendwann wieder getrennt und als Folge daraus muss ich das MyClient-Objekt auch wieder löschen. Das Mache ich, wenn zb. das
Socket das disconnected() Signal sendet, Sendet MyClient ein Signal mit dem Pointer auf sich selber an das Serverobjekt um die Pointer aus QList und QHash zu löschen,
danach wendet er ein deleteLater() auf das MyClient-Objekt an. Das wäre jetzt mal der grobe Ablauf, doch jetzt habe ich ein paar Szenarios bei denen ich unsicher bin:
1. Die Verbindung wird getrennt, aber im Threadpool wird noch ein Befehl von der Verbindung ausgeführt. Der Thread antwortet ja mit einem Signal, aber was passiert
wenn das entsprechende MyClient-Objekt schon gelöscht wurde ? Falls es dadurch zu Problemen kommen könnte, würde ich folgendes machen:
( Da das Server-Objekt, das MyClient-Object und das erzeugen des QRunnable-Objects in einem Thread liegen ) Bevor ich den Thread im Threadpool starte könnte ich eine Variable in MyClient um 1 erhöhen ,wenn der Thread die Antwort gesendet hat, könnte ich sie wieder um 1 erniedrigen und das Object darf nur gelöscht werden, wenn die Variable 0 ist. Falls sie nicht 0 ist starte ich einen Timer auf zb 1 sec und versuche dann eine erneute löschung. Aber ist dies wirklich nötig ?
myclient.h
Code: Alles auswählen
#ifndef MYCLIENT_H
#define
MYCLIENT_H
#include <QObject>
#include <QTcpSocket>
#include <QDebug>
#include <QThreadPool>
#include <QByteArray>
class MyClient : public QObject
{
Q_OBJECT
public:
explicit MyClient(QObject *parent = 0);
void SetSocket(int Descriptor);
void readnextBlockSize();
signals:
void delete_client(MyClient*);
public slots:
void
connected();
void disconnected();
void readyRead();
void send(QByteArray);
private:
QTcpSocket *socket;
quint32 nextBlockSize;
};
#endif // MYCLIENT_H
Code: Alles auswählen
#include "myclient.h"
#include "task_receivedata.h"
#include <QThreadPool>
MyClient::MyClient(QObject *parent) :
QObject(parent)
{
nextBlockSize = 0;
connect(this,SIGNAL(delete_client(MyClient*)),parent,SLOT(delete_unidentified_connection(MyClient*)));
}
void MyClient::SetSocket(int Descriptor)
{
socket = new QTcpSocket(this);
connect(socket,SIGNAL(connected()),this,SLOT(connected()));
connect(socket,SIGNAL(disconnected()),this,SLOT(disconnected()));
connect(socket,SIGNAL(readyRead()),this,SLOT(readyRead()));
socket->setSocketDescriptor(Descriptor);
qDebug() << "client connected";
}
void MyClient::connected()
{
qDebug() << "client connected event";
}
void MyClient::disconnected()
{
qDebug() << "client disconnected";
emit delete_client(this);
}
void MyClient::send(QByteArray array)
{
socket->write(array);
}
void MyClient::readyRead()
{
if(nextBlockSize == 0 && socket->bytesAvailable() >= 4)
{
readnextBlockSize();
qDebug() << nextBlockSize;
}
if(nextBlockSize != 0 && socket->bytesAvailable() >= nextBlockSize)
{
qDebug() << "Thread start";
task_receivedata *receivedata = new task_receivedata(socket->read(nextBlockSize),nextBlockSize);
receivedata->setAutoDelete(true);
connect(receivedata,SIGNAL(send_data(QByteArray)),this,SLOT(send(QByteArray)),Qt::QueuedConnection);
QThreadPool::globalInstance()->start(receivedata);
nextBlockSize = 0;
return;
}
}
void MyClient::readnextBlockSize()
{
QByteArray blocksize(socket->read(4));
union
{
char Blocksizein[4];
quint32 BlockSizeout;
} x;
char *p = x.Blocksizein;
*p++ = blocksize[0];
*p++ = blocksize[1];
*p++ = blocksize[2];
*p = blocksize[3];
nextBlockSize = x.BlockSizeout;
}