Seite 1 von 1

TcpSocket`s "ReadyRead" als Thread

Verfasst: 18. Mai 2010 13:08
von Mineralwater
Hallo Leute!
Seit mehreren Wochen schon zerbreche ich mir den Kopf darüber und bekomms nicht wirklich hin...

Folgendes Problem:
Der Client meldet sich am Server an und bekommt 3 Pakete hintereinander zugesendet...
Wenn der Client nun das erste Paket abarbeitet darf`s nicht zu lange dauern weil sonst der Thread blockiert und ReadyRead nicht wieder "anschlagen" kann. Manchmal hatte ich auch sogar Problem das die Pakete ineinander verschachtelt ankamen.

Deswegen will ich eigentlich das mein ReadyRead nur prüft ob ein Paket reinkommt, kurz puffert und dann ein Signal gibt, so das mein MainWindow das Paket abarbeiten kann. Aber selbst das haut nicht wirklich hin, weil dann mein drittes Paket leider verloren geht sobald ich 10ms pausiere (zur Simulation dienend). :(

Im MainWindow erstellt:

Code: Alles auswählen

tcpSocket  = new ClientTcpSocket(settings);
connect(tcpSocket,   SIGNAL(bufferReady(QByteArray)),  this,  SLOT   (getBuffer(QByteArray)));

tcpSocket->loginOnServer();

void MainWindow::getBuffer(QByteArray buffer){
    qDebug() << "Das Paket wird abgearbeitet... (simulierte 10ms)";
    SleeperThread::msleep(10);
}

ClientTcpSocket-Klasse

Code: Alles auswählen

ClientTcpSocket::ClientTcpSocket(ClientSettings *settings, QObject *parent) : QThread(parent)
{
    m_settings      = settings;
    m_socket        = new QTcpSocket;
}

void ClientTcpSocket::run()
{
    connect(m_socket, SIGNAL(readyRead()), this, SLOT(readClientData()));
    exec();
}

void ClientTcpSocket::readClientData()
{
    qDebug() << "ClientTcpSocket... Bekomme Daten rein...";

    QDataStream in(m_socket);
    in.setVersion(QDataStream::Qt_4_6);
    in >> m_buffer;

    emit bufferReady(m_buffer);
}

void ClientTcpSocket::loginOnServer()
{
    if(!m_socket->isOpen())
    {
            m_socket->connectToHost("...","...");
            if(m_socket->waitForConnected(2000))
            {
                start();    // QThread anlaufen lassen...

                m_socket->write("loginDaten"); // Daten an Server senden
            }
            else{
                qDebug() << "Fehler, keine Verbindung hergestellt";
            }
    }
}
Bin für jeden Tipp dankbar :!:
Vielen Dank schonmal im vorraus.

Gruß

Mineralwater

Verfasst: 18. Mai 2010 16:27
von Christian81
So richtig verstehe ich das Problem nicht. Sobald neue Daten ankommen wird readyRead() emittiert. Die Signale gehen defintiiv nicht verloren - egal wie lange eine Funktion die Eventloop blockiert.
Was Du allerdings nicht machst ist solange Daten zu lesen wie Daten vorhanden sind. Du liest einfach ein Paket und fertig. Wenn aber 2 Pakete zusammen angekommen sind liest Du das zweite auch nicht (und bekommst natürlich auch kein readyRead() - es sind ja keine neuen Daten angekommen).

Des weiteren läuft deine Thread-Lösung auch komplett im Mainthread - m_socket wird im MainThread erzeugt und auch ClientTcpSocket selbst lebt im MainThread. Aber Threads brauchst Du hier ja auch nicht.

Verfasst: 19. Mai 2010 08:27
von RHBaum
und noch ne Anmerkung, auch wenns ned zum Thema gehört:

Initialisierungslisten sind ein tolles c++ feature, und erspart Dir oft anderweitig Ärger. Nutze sie, auch bei der QT:

Code: Alles auswählen

ClientTcpSocket::ClientTcpSocket(ClientSettings *settings, QObject *parent):
QThread(parent),
m_settings(settings),
m_socket(new QTcpSocket(this))
{
  
} 
spaetestens wenn mal ohne den autodelete Mechanismus und ohne QT Abhaengigkeiten auskommen musst, werden Smartpointer statt rohe pointer attraktiv und da wirst um die initialisierung bei erzeugung eh ned drumherumkommen !

Ciao ...

Verfasst: 27. Mai 2010 19:54
von trendyAndy
Sollte bei dem Beispiel nicht eine Fehlermeldung im Application Output kommen? Sowas wie

QObject:Cannot create children for a parent that is in a different thread.

weil der Socket nicht im Thread selber erzeugt wird sondern im MainThread?? So wie Christian das schon richtig gesagt hat.

Deshalb geht auch der Connect nicht glaube ich, bzw.wäre das evtl. eine Erklärung dafür.
Ich habe daraufhin den Socket im run() erzeugt und alles geht wunderbar.

Gruß