QT Multithreaded Statefull Server
QT Multithreaded Statefull Server
------
Zuletzt geändert von psy_cho am 6. November 2009 23:19, insgesamt 1-mal geändert.
Der Thread lebt schon lange genug... obwohl ich die Eventloop-Methode für viel eleganter (echte Statemachine) halte, denke ich auch es müsste eine Lösung auf diesem Weg geben. Die einzigen Punkte die ich sehe sind folgende:
1. Nach dem connect würde ich auf die Verbindung warten:
Keine Ahnung was bei einem "write(..)" im Zustand "QAbstractSocket::ConnectingState" geschieht...
2. "sock->flush();" ist IMHO unnötig... nach waitForBytesWritten() gibt es ja nichts mehr zu senden..
1. Nach dem connect würde ich auf die Verbindung warten:
Code: Alles auswählen
sock->connectToHost(QString("127.0.0.1"),(qint16)1643);
sock->waitForConnected(-1);2. "sock->flush();" ist IMHO unnötig... nach waitForBytesWritten() gibt es ja nichts mehr zu senden..
Hi,
ich vermute einem "DeadLock".
Kannst Du bitte noch den Server dazu posten? (virtualmanageragent.h, virtualmanageragent.cpp??) Je nachdem in welcher Reihenfolge das Empfangen und Senden geschieht, kann es sein, dass beide Prozesse aufeinander warten.
Hast Du mal im Debug geschaut wo der Client stecken bleibt? In waitForBytesWritten oder in waitForReadyRead?
Zum Thema flush() sagt die Qt Doku:
Grüße
André
PS
Hab sowas noch nie mit Qt Mitteln gemacht, sondern mit Standard C Funktionen ...
ich vermute einem "DeadLock".
Kannst Du bitte noch den Server dazu posten? (virtualmanageragent.h, virtualmanageragent.cpp??) Je nachdem in welcher Reihenfolge das Empfangen und Senden geschieht, kann es sein, dass beide Prozesse aufeinander warten.
Hast Du mal im Debug geschaut wo der Client stecken bleibt? In waitForBytesWritten oder in waitForReadyRead?
Zum Thema flush() sagt die Qt Doku:
Also weglassen und waitForBytesWritten aufrufen! Oder -meine Meinung- direkt nach dem write() und anschliessend waitForBytesWritten() aufrufen. Wird aber nichts am Problem ändern.... In the absence of an event loop, call waitForBytesWritten() instead.
Grüße
André
PS
Hab sowas noch nie mit Qt Mitteln gemacht, sondern mit Standard C Funktionen ...
Ich würde an deiner Stelle genauestens überlegen, ob du eine multi-threaded Lösung überhaupt brauchst. Meine Erfahrung zeigt, dass die Benutzung von mehr als 2 Threads innerhalb einer Anwendung oft die Folge von falschen architektonischen Entscheidungen ist...psy_cho hat geschrieben:Ich hab damit in Verbindung von OpenGL und QT sehr schlechte Erfahrungen gemacht. Was laut doku hätte funktionieren müssen tat es nicht wie ihm geheißen.
Ich hab nix gegen echte Signals, so wie sie zwischen Posix Threads oder Prozessen gesendet werden können. Weil ich da entscheide in welchem Thread diese abgearbeitet werden.
Ich bin generell kein freund dieser Callback Konzepte, da man bei multithreaded Anwendungen recht schnell aus den Augen verlieren kann in welchem Kontext den nun eine Methode aufgerufen wird.
Ich tendiere eher zu transparentem Informationsfluss innerhalb einer Anwendung.
Ich hab natürlich auch nichts gegen eine Signal Slot Lösung. Wenn sie multithreaded arbeitet und gut funktioniert.
Mfg
Marc
nicht-transparenter Code und dein Code haben was gemeinsam: beide funktionieren nicht ...
Mal abgesehen davon, dass du (soweit wir in das Projekt sehen) wirklich noch nirgends ein Thread benötigen würdest, habe ich dafür keine 24h, keine 20min sondern gerademal 5-10min benötigt:
hth..
[EDIT] PS.
Qt kann nicht alles und ist auch nicht fehlerfrei, aber OpenGL/Qt/Signals/Slots arbeiten (bei richtiger Anwendung) hervorragend...
Mal abgesehen davon, dass du (soweit wir in das Projekt sehen) wirklich noch nirgends ein Thread benötigen würdest, habe ich dafür keine 24h, keine 20min sondern gerademal 5-10min benötigt:
Code: Alles auswählen
#ifndef _PING_
#define _PING_
#include <QThread>
class Ping: public QThread
{
public:
virtual void run();
};
#endif
Code: Alles auswählen
#ifndef _PONG_
#define _PONG_
#include <QThread>
class Pong: public QThread
{
public:
virtual void run();
};
#endifCode: Alles auswählen
#include <QDebug>
#include <QTcpSocket>
#include <QTcpServer>
#include "ping.h"
void Ping::run()
{
QTcpServer primaryServer;
qDebug() << "Ping: warte auf Client";
primaryServer.listen(QHostAddress::Any,1643);
primaryServer.waitForNewConnection(-1);
QTcpSocket* newConnection = primaryServer.nextPendingConnection();
newConnection->waitForConnected(-1);
qDebug() << "Ping: Verbunden";
while (1) {
qDebug() << "Ping: sende ping";
newConnection->write("ping");
newConnection->waitForBytesWritten(-1);
qDebug() << "Ping: warte auf Antwort";
newConnection->waitForReadyRead(-1);
qDebug() << "Ping: Antwort erhalten" << newConnection->readAll();
}
}Code: Alles auswählen
#include <QDebug>
#include <QTcpSocket>
#include "pong.h"
void Pong::run()
{
QTcpSocket newConnection;
do {
newConnection.connectToHost("localhost",1643);
} while (!newConnection.waitForConnected(1000));
qDebug() << "Pong: Verbunden";
while (1) {
qDebug() << "Pong: warte auf Antwort";
newConnection.waitForReadyRead(-1);
qDebug() << "Pong: Antwort erhalten" << newConnection.readAll();
qDebug() << "Pong: sende pong";
newConnection.write("pong");
newConnection.waitForBytesWritten(-1);
}
}Code: Alles auswählen
#include <QCoreApplication>
#include "ping.h"
#include "pong.h"
int main(int argc, char *argv[])
{
QCoreApplication app(argc,argv);
Ping t1;
Pong t2;
t1.start();
t2.start();
return app.exec();
}[EDIT] PS.
Qt kann nicht alles und ist auch nicht fehlerfrei, aber OpenGL/Qt/Signals/Slots arbeiten (bei richtiger Anwendung) hervorragend...
Mag sein, dass es funktioniert.
Aber es ist wieder nicht das was ich suche. Ich will die neu aufgebaute Verbindung einem Thread übergeben, der diese bearbeitet. Ein vorgehen, was sich über Jahr hinweg erfolgreich behauptet hat. Also kann es net so schlecht sein.
Das Problem was ich festgestellt hab ist das waitForReadyRead nie zurück kehrt. Muss es aber, da Daten über die Verbindung gelaufen sind. Kann man ja mit Wireshark, etc prüfen.
Aber es ist wieder nicht das was ich suche. Ich will die neu aufgebaute Verbindung einem Thread übergeben, der diese bearbeitet. Ein vorgehen, was sich über Jahr hinweg erfolgreich behauptet hat. Also kann es net so schlecht sein.
Das Problem was ich festgestellt hab ist das waitForReadyRead nie zurück kehrt. Muss es aber, da Daten über die Verbindung gelaufen sind. Kann man ja mit Wireshark, etc prüfen.
Jetzt schlägt's aber 13.
Ich hab dein Beispiel nochmal so Modifiziert, dass es die neue Verbindung in einen eigenen Thread packt. Und es geht.
Ich mach in meinem Code semantisch 1:1 das gleiche.
Aber der waitForReadyRead kommt net zurück. Ich glaub ich
leg das Projekt nochmal neu an.
Vllt stimmt da irgendwas im Projekt file net
Ich hab dein Beispiel nochmal so Modifiziert, dass es die neue Verbindung in einen eigenen Thread packt. Und es geht.
Ich mach in meinem Code semantisch 1:1 das gleiche.
Aber der waitForReadyRead kommt net zurück. Ich glaub ich
leg das Projekt nochmal neu an.
Vllt stimmt da irgendwas im Projekt file net