QTcpSocket auf dem Heap anlegen?

Alles rund um die Programmierung mit Qt
Viper2000
Beiträge: 48
Registriert: 7. Mai 2008 16:36

QTcpSocket auf dem Heap anlegen?

Beitrag von Viper2000 »

Hallo,

habe ein Programm geschrieben was bei jeder eingehenden Clientverbindung eines QServerSocket einen Thread erzeugt, der dann die Clientkommunikation abwickelt.
In diesem "ClientThread" hab ich jetzt zwei möglichkeiten probiert. Einmal den Socket mit

QTcpsocket tcpSocket;

und einmal mit

QTcpsocket *tcpSocket; und später tcpSocket = new QTcpSocket();

erzeugt.
Also im zweiten Fall dynamisch auf dem Heap.

Hänge auch nochmal beide CPP Dateien hier an. Mir sind die Vor- und Nachteile dieser zwei Möglichkeiten noch nicht so wirklich klar. Vielleicht kann jemand was dazu sagen.

Fall 1: Socket mit "QTcpSocket tcpSocket" in der Header.

Code: Alles auswählen

//FILE: clientThread.cpp
#include "clientThread.h"
#include <QtNetwork>

ClientThread::ClientThread(int socketDescriptor, QObject *parent)
	: QThread(parent), socketDescriptor(socketDescriptor)
{
	qDebug("***ClientThread constructed***");
	connect(&tcpSocket, SIGNAL( readyRead() ), this, SLOT( readFortune() ) );
	connect(&tcpSocket, SIGNAL( disconnected() ), this, SLOT( setDisconnect() ) );
	connect(this, SIGNAL( finished() ), this, SLOT( deleteLater() ) );
	
	if( !tcpSocket.setSocketDescriptor( socketDescriptor ) )
	{
		emit error(tcpSocket.error());
		return;
	}
	//sendWelcome();

	qDebug() << "Client Address: " << tcpSocket.peerAddress().toString();
}
Fall 2: Socket mit "QTcpSocket *tcpSocket" in der Header.

Code: Alles auswählen

//FILE: clientThread.cpp
#include "clientThread.h"
#include <QtNetwork>

ClientThread::ClientThread(int socketDescriptor, QObject *parent)
	: QThread(parent), socketDescriptor(socketDescriptor)
{
       tcpSocket = new QTcpSocket();
	qDebug("***ClientThread constructed***");
	connect(tcpSocket, SIGNAL( readyRead() ), this, SLOT( readFortune() ) );
	connect(tcpSocket, SIGNAL( disconnected() ), this, SLOT( setDisconnect() ) );
	connect(this, SIGNAL( finished() ), this, SLOT( deleteLater() ) );
	
	if( !tcpSocket->setSocketDescriptor( socketDescriptor ) )
	{
		emit error(tcpSocket->error());
		return;
	}
	//sendWelcome();

	qDebug() << "Client Address: " << tcpSocket->peerAddress().toString();
}
Ich bin nicht die Signatur, ich putz hier nur :-)
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

In beiden Fällen liegt es auf dem Heap da Du ClientThread bestimmt mit new() erzeugst.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Viper2000
Beiträge: 48
Registriert: 7. Mai 2008 16:36

Beitrag von Viper2000 »

ich wusste nicht, dass wenn man ne Klasse(hier Thread) mit new() Erzeugt auch alles interne der Klasse dann auf dem Heap liegt. Klingt aber logich ;)

Soll das also heißen, dass es gehoppt wie gesprungen ist welche Methode ich anwende!?
Ich bin nicht die Signatur, ich putz hier nur :-)
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Mehr oder weniger ja - kommt eben drauf an ob Du am Ende ein delete machen willst oder nicht. Aber selbst das erübrigt sich ja meistens wenn man einen parent mit angibt. Und da Qt-Klassen intern sowieso alles in einer privaten Klasse anlegen die per new() erzeugt wird liegt gar nicht so viel auf dem Stack wie man annimmt.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Viper2000
Beiträge: 48
Registriert: 7. Mai 2008 16:36

Beitrag von Viper2000 »

ok, habe grad mal in das "Threaded Fortune Server Example" in der Qt4 Dokumentation geschaut. Dort nutzen sie den Heap nicht. Lediglich der einmalig erzeugte QTcpServer wird auf dem Heap angelegt.

Allerdings wird dort jeder Thread sofort wieder beendet und bekommt keine eigene Eventloop wie bei mir im Projekt. Meine Threads laufen solange bis ein Client sich wieder Disconnected. Dann wird der Thread deleted.
Ich bin nicht die Signatur, ich putz hier nur :-)
Maxima
Beiträge: 27
Registriert: 23. Mai 2008 03:45

Beitrag von Maxima »

Ich habe bei mir eine Klasse generiert, die die TcpSockets sammelt und es funktioniert ganz gut, deswegen die Frage:
Ist es in Deiner Anwendung nötig für jeden TcpSocket einen eigenen thread (mit eigener event-loop) anzulegen? Wo sind die Vorteile?
Viper2000
Beiträge: 48
Registriert: 7. Mai 2008 16:36

Beitrag von Viper2000 »

Hi, ja es war eigentlich so gedacht, dass für jede Clientverbindung ein eigener Thread gestartet wird.

Ich dachte das wäre die Standard Vorgehensweise für jeden cleint nen Thread zu eröffnen...

Kannste mir deine Thread-Sammelklasse mal zeigen!?
Ich bin nicht die Signatur, ich putz hier nur :-)
Maxima
Beiträge: 27
Registriert: 23. Mai 2008 03:45

Beitrag von Maxima »

Code: Alles auswählen

class MyConnection : public QObject
{
...
signals:
...
slots:
...
private:
QTcpSocket * tcp;
...
};

QList<MyConnection*> socketListe;

die class hat slots und signals für die Außen-Welt
Weis nicht ob das hilfreich für Dich ist...
(BTW: ist auch aus dem fortuneserver entstanden, der ja einfach einen TcpSocket mit connect-slot-signals verknüpft und bei disconnect dann löscht ohne eine Liste zu benutzen)

Bis jetzt reicht es für mich, aber es ist spannend zu wissen, was hier (TcpSockets) der Vorteil eines Threads ist/sein könnte.
Zuletzt geändert von Maxima am 23. Mai 2008 12:20, insgesamt 1-mal geändert.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

QList<MyConnection> socketListe;
Wirklich? Kann nämlich nicht gehen :)
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Maxima
Beiträge: 27
Registriert: 23. Mai 2008 03:45

Beitrag von Maxima »

danke, korrigiert :D
keeney
Beiträge: 9
Registriert: 14. September 2007 01:56
Wohnort: Regensburg
Kontaktdaten:

Beitrag von keeney »

Wenn der Server viele Clients handlen soll, dann wuerd ich dir empfehlen, einen Threadpool zu verwenden, sonst steigt dir das Betriebssystem irgendwann auf's Dach. Und bedenke, dass jeder erzeugte Thread Speicher verbraucht, und das nicht wenig.
Viper2000
Beiträge: 48
Registriert: 7. Mai 2008 16:36

Beitrag von Viper2000 »

Wir reden hier in meinem Fall in der Größenordnung von 5 oder 6 Clients. Also 5 oder 6 Threads...

Ich dachte mir bisher, da ich auf das readyRead() Signal einer jeden Verbindung reagieren will, dass ich für jede Verbindung einen eigenen Thread kreiere und in jedem Thread eine eigene EventLoop laufen lasse.

In ersten Tests funktioniert soweit auch alles.

Jetzt habt ihr mich aber verunsichert und ich weiß nichtmehr was ich machen soll - dafür bin ich zu unerfahren auf dem Gebiet. Komme eher aus der Mikrocontroller sparte :lol: :lol: :lol:
Ich bin nicht die Signatur, ich putz hier nur :-)
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Für fünf bis 6 Threads ist das allemal ok so wie du es gemacht hast. Zumal Du ja die threads auch recht schnell wieder löschst.
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
Maxima
Beiträge: 27
Registriert: 23. Mai 2008 03:45

Beitrag von Maxima »

Viper2000 hat geschrieben:Jetzt habt ihr mich aber verunsichert und ich weiß nichtmehr was ich machen soll - dafür bin ich zu unerfahren auf dem Gebiet. Komme eher aus der Mikrocontroller sparte :lol: :lol: :lol:
Sorry, die Frage sollte Dich nicht verunsichern! :)
Ich dachte/denke, daß alle etwas lernen können, wenn wir sowas diskutiert.

Beide Ansätze funktionieren ja ganz gut, die Frage war/ist wo die Grenzen der einzelnen Methoden wären.
Eine gute Einsicht ist ja schon mal, daß threads mehr Speicher verbrauchen.

Das (die limits) können wir ja hier ergänzen, wenn wir sie erreichen sollten.

:)
Viper2000
Beiträge: 48
Registriert: 7. Mai 2008 16:36

Beitrag von Viper2000 »

Ja klar, ein Forum ist ja zum Diskutieren gedacht :)

Also meine Methode:
Bei jedem Client der connected einen eigenen Thread erzeugen und in diesem Thread eine Eventloop mit "exec" starten und auf Signale wie z.B. "readyRead()" reagieren. Der Thread bleibt solange mit seiner Eventloop bestehen bis der Client sich vom Server disconnected!
Deine Methode:
Bei jeder eingehenden Clientverbindung eine Klasse auf dem Heap mit new instanzieren, welche die Funktionalität der Kommunikation enthält. Die Objekte der Klassen dann in eine QList packen. Auf Threads wird vollkommen vezichtet.
So ist das doch richtig Maxima oder...

Auch alle anderen mit viel Erfahrung sind gefragt welche Vorgehensweise sie bevorzugen würden.
Ich bin nicht die Signatur, ich putz hier nur :-)
Antworten