QThread für QTCPSocket benutzen

Alles rund um die Programmierung mit Qt
solarix
Beiträge: 1133
Registriert: 7. Juni 2007 19:25

Beitrag von solarix »

@Christian: hmm... es gibt doch folgend zwei Scenarien:

1. QTcpSocket und FortuneServer gehören zu unterschiedlichen Eventloops:
- Der QTcpSocket hat als Parent QTcpServer und wurde nicht mit moveToThread() verschoben
- Eine Signal-Slot-Connection vom Socket zum Server wird dann per AutoConnection zu einer "QueuedConnection"
- der Slot wird aber trotzdem im Kontext des Threads aufgerufen
- welcher dann irgendwas mit QTcpSocket macht (Lesen/Schreiben)
-> hast Recht: das führt zu Probleme, weil dann evt. parallel auf dem Socket gearbeitet wird...

2. der Socket und der FortuneServer gehören zur gleichen Eventloop
- der Socket muss mit "setParent(NULL)" und "moveToThread()" verschoben werden
- Die AutoConnection ergibt eine DirectConnection innerhalb des Eventloops des Threads.
-> keine Probleme

Mein Beispielcode könnte bleiben wie er ist, aber der Kontruktor sähe dann so aus:

Code: Alles auswählen

FortuneServer::FortuneServer(QTcpSocket *sock) 
  ...
{
  sock->setParent(NULL);
  sock->moveToThread(this); // wir sind noch im Kontext der GUI.. ist ok..
}
hth!
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

So sollte es korrekt sein, ja :)
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
dazedly
Beiträge: 197
Registriert: 3. Oktober 2010 15:38
Kontaktdaten:

Beitrag von dazedly »

Wichtig ist, dass du beim QTcpServer nich das Signal, sondern "void QTcpServer::incomingConnection ( int socketDescriptor ) [virtual protected]"
benutzt. Dort bekommst du einen descriptor und du kannst in deinem Thread nen Socket aufmachen.
Das Problem ist, wenn du das anderes machst, hast du 2 tcpsockets mit dem selben Descriptor und unter linux ist es dann mehr oder weniger zufall, an welchen deiner Sockets deine Daten geschickt werden, aus diesem Grund funktioniert dein readyRead auch nicht mehr richtig.


"void QTcpServer::incomingConnection ( int socketDescriptor ) [virtual protected]"

This virtual function is called by QTcpServer when a new connection is available. The socketDescriptor argument is the native socket descriptor for the accepted connection.
The base implementation creates a QTcpSocket, sets the socket descriptor and then stores the QTcpSocket in an internal list of pending connections. Finally newConnection() is emitted.
Reimplement this function to alter the server's behavior when a connection is available.
If this server is using QNetworkProxy then the socketDescriptor may not be usable with native socket functions, and should only be used with QTcpSocket::setSocketDescriptor().
Note: If you want to handle an incoming connection as a new QTcpSocket object in another thread you have to pass the socketDescriptor to the other thread and create the QTcpSocket object there and use its setSocketDescriptor() method.
See also newConnection(), nextPendingConnection(), and addPendingConnection().
anno1988
Beiträge: 280
Registriert: 23. Januar 2009 20:49

Beitrag von anno1988 »

k danke für die hilfe soweit mal.

HTTP funktioniert bei mir jetzt soweit mal mit der Kommunikation mit Firefox.

Allerdings will ich noch HTTPS ausprobieren und da habe ich noch ein Problem. Friefox enthält keine Daten, sobald ich per SSL zugreifen will.
HTTP geht ohne Probleme.

Bei der HTTPS Verbindung funktioniert die Verbindung an Sich schon. Im Firefox kann ich das Zertifikat herunterladen, anschauen usw., allerdings sehe ich nie Daten, die ich mit übertragen habe.

Habe ich da irgendwas vergessen, was man noch rein machen müsste im QSslSocket, dass Firefox die daten akzeptiert?

Code: Alles auswählen


QSslSocket *sslssocket;
...
...

void Webfrap_Server::incomingConnection(int socketDescriptor) {

sslssocket = new QSslSocket();
sslssocket->setSocketDescriptor(socketDescriptor);
		sslssocket->setLocalCertificate("/home/anno/Desktop/ssl/meropis.pem");
		sslssocket->setPrivateKey("/home/anno/Desktop/ssl/meropis.pem");

		connect(sslssocket, SIGNAL(readyRead()), this, SLOT(readData()));

		ssls->startServerEncryption();

}


void readData() {

		if(sslssocket->canReadLine()) {

			QStringList tokens = QString(sslssocket->readAll()).split(QRegExp("[ \r\n][ \r\n]*"));

			if (tokens[0] == "GET") {

				QByteArray block;

				block.append("HTTP/1.0 200 Ok\r\nContent-Type: text/html; charset=\"utf-8\"\r\n\r\n<h1>Nothing to see here</h1>\n" + QDateTime::currentDateTime().toString());

				sslssocket->write(block);


				qDebug() << "GET";


				sslssocket->close();

			}
		}
anno1988
Beiträge: 280
Registriert: 23. Januar 2009 20:49

Beitrag von anno1988 »

ok habs herausgefunden woran es lag. Ich muss den Socket mit disconnectFromHost schließen.
anno1988
Beiträge: 280
Registriert: 23. Januar 2009 20:49

Beitrag von anno1988 »

Gibt es in Qt eigentlich eine Klasse mit der man das HTTP Protokoll handeln kann?

Ich habe bis jetzt nur QHttp gefunden, aber diese soll man ja nicht mehr verwenden, da sie veraltet ist.

Mir würde es da eigentlich ja schon reichen, wenn nur das Protokoll gehandelt wird, da die Verbindung ja schon mit einem Socket aufgebaut wird.
franzf
Beiträge: 3114
Registriert: 31. Mai 2006 11:15

Beitrag von franzf »

anno1988 hat geschrieben:Ich habe bis jetzt nur QHttp gefunden, aber diese soll man ja nicht mehr verwenden, da sie veraltet ist.
Das steht doch in der Doku zu QHttp...
anno1988
Beiträge: 280
Registriert: 23. Januar 2009 20:49

Beitrag von anno1988 »

Na also wenn ich jetzt z.b. den QNetworkAccessmanager nehme, dann ist da drin ja schon eine Unterstützung für Sockets usw. vorhanden und das kann ich ja dann mit dem QTcpServer zusammen nicht mehr nehmen. Aber in diesem QNetworkAccessmanager ist ja schon die HTTP Protokoll Unterstützung mit drin.

Aber ich habe jetzt ja schon eine Unterstützung für QTcpSockets implementiert.
Antworten