Seite 1 von 1

QT Multithreaded Statefull Server

Verfasst: 6. November 2009 01:32
von psy_cho
------

Verfasst: 6. November 2009 08:23
von Mani99
Du solltest event. in der run() methode noch ein "exec()" aufrufen, dann lebt der thread "etwas" länger!

Verfasst: 6. November 2009 09:19
von solarix
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:

Code: Alles auswählen

sock->connectToHost(QString("127.0.0.1"),(qint16)1643); 
sock->waitForConnected(-1);
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..

Verfasst: 6. November 2009 13:37
von dikilroy
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:
... In the absence of an event loop, call waitForBytesWritten() instead.
Also weglassen und waitForBytesWritten aufrufen! Oder -meine Meinung- direkt nach dem write() und anschliessend waitForBytesWritten() aufrufen. Wird aber nichts am Problem ändern.

Grüße
André

PS
Hab sowas noch nie mit Qt Mitteln gemacht, sondern mit Standard C Funktionen ...

Verfasst: 6. November 2009 14:57
von psy_cho
----------------------------

Verfasst: 6. November 2009 16:29
von pfid
Gibts nen Grund dafür, dass du so eisern drauf bestehst, keine Signals & Slots zu verwenden?

Verfasst: 6. November 2009 18:05
von psy_cho
--------------------------------------------------------------------------

Verfasst: 6. November 2009 18:33
von lepsai
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
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...

Verfasst: 6. November 2009 19:27
von solarix
nicht-transparenter Code und dein Code haben was gemeinsam: beide funktionieren nicht ... :roll:

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();
};
#endif

Code: 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();
}
hth..

[EDIT] PS.
Qt kann nicht alles und ist auch nicht fehlerfrei, aber OpenGL/Qt/Signals/Slots arbeiten (bei richtiger Anwendung) hervorragend...

Verfasst: 6. November 2009 23:05
von psy_cho
@solarix

Früher hätte ich mir die Mühe gemacht, dass mit dir zu diskutieren.
Mittlerweile sag ich einfach "Danke", den Rest kannst du dir denken.
Auf solch unqualifizierte Antworten leg ich keinen Wert.

Wieder eine wertvolle Erfahrung gemacht hier.

In diesem Sinne.

Verfasst: 6. November 2009 23:15
von solarix
Soweit so gut. Das Problem taucht jetzt beim Auslesen auf.
Warte ich mit QTcpSocket::waitForReadyRead(-1) blockierend auf Input vom Socket ist der Ofen aus. Der Thread blockiert.
Das Beispiel funktioniert doch, oder nicht?

Verfasst: 6. November 2009 23:22
von psy_cho
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.

Verfasst: 6. November 2009 23:49
von psy_cho
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