[C++/QT] QUdpSocket geeft geen readyRead()

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • Xerohumoris
  • Registratie: Augustus 2010
  • Laatst online: 02-10 17:31
Mijn vraag
Ik heb in een programma gebruik gemaakt van de QUdpSocket. Echter als er een datapakket binnen komt geeft het geen QUdpSocket::readyRead(). Wat doe ik verkeerd?

Relevante software en hardware die ik gebruik
gcc version 10.2.1 20201202
Using Qt version 5.15.2

Wat ik al gevonden of geprobeerd heb
Ik heb 2x hetzelfde programma geschreven. De eerste keer was een kleine proef en zou te complex worden om er mee door te gaan. Dit programma werkte goed en de QUdpSocket deed exact wat ik verwachte. Ik zal dan ook eerst de werkende code van het oude programma geven.

Connection.h:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#ifndef CONNECTIONZ21_H
#define CONNECTIONZ21_H

#include <QObject>
#include <QUdpSocket>
#include <QSettings>

class ConnectionZ21  : public QObject
{
    Q_OBJECT
public:
    ConnectionZ21(QObject *parent = nullptr);
    virtual ~ConnectionZ21() {}

private:
    QUdpSocket *Connection;
    QHostAddress IPAdress;
    int Port;

public slots:
    void sender(QByteArray fullData);

signals:
    void toLog(QString message);
    void toReceiver(QByteArray data);

private slots:
    void receiver();

};

#endif // CONNECTIONZ21_H


Connection.cpp
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include "Connection.h"

ConnectionZ21::ConnectionZ21(QObject *parent) : QObject(parent)
{
    QSettings Settings;
    IPAdress.setAddress(Settings.value("connection/IP").toString());
    Port = Settings.value("connection/port").toInt();
    Connection = new QUdpSocket();
    Connection->bind(IPAdress, Port);

    connect(Connection, SIGNAL(readyRead()),
            this, SLOT(receiver()));

}

void ConnectionZ21::sender(QByteArray fullData)
{
    Connection->writeDatagram(fullData, IPAdress, Port);
    //emit toLog("Sending: " + fullData.toHex());
    qDebug() << "Sending: " << fullData.toHex();
}

void ConnectionZ21::receiver()
{
    QByteArray replyData;
    //emit toLog("Receiving data");
    while (Connection->hasPendingDatagrams()){
        replyData.resize(int(Connection->pendingDatagramSize()));
        Connection->readDatagram(replyData.data(), replyData.size());
    }
    emit toReceiver(replyData);
    //emit toLog(replyData.toHex());
    qDebug() << "Receiving: " << replyData.toHex();
}


Dit geeft de volgende output:
code:
1
2
3
4
5
6
7
8
Sending:  "080050000f0d0107"
Receiving:  "140084004600030043001e00b94b2c4400000000"
Receiving:  "140084005e00030042001e00ef4b834500000000"
Receiving:  "140084005300030043001e00c24bb64300000000"
Receiving:  "140084005300030041001e00f84b894300000000"
Receiving:  "140084005c00030041001e00f84bfe4300000000"
Receiving:  "140084005800030042001e00dd4b2c4400000000"
Receiving:  "140084005600030043001e00e64b234400000000"


Dan nu de code die niet werkt.

Connection.h
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#ifndef Z21_CONNECTION_H
#define Z21_CONNECTION_H

#include "Z21_Connection_global.h"
#include <QObject>
#include <QUdpSocket>
#include <QDebug>

class Z21_CONNECTION_EXPORT Z21_Connection : public QObject
{
    Q_OBJECT
public:
    Z21_Connection(QObject *parent = nullptr);
    virtual ~Z21_Connection() {}

private:
    QUdpSocket *Connection;
    QHostAddress IPAdress;
    int Port = 21105;

public slots:
    void send(QByteArray data);

private slots:
    void reader();

signals:
    void toParser(QByteArray data);
};

#endif // Z21_CONNECTION_H


Connection.cpp
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include "Connection.h"

Z21_Connection::Z21_Connection(QObject *parent) :QObject(parent)
{
    //first we do static for testing
    IPAdress.setAddress("192.168.0.111");
    Connection = new QUdpSocket();
    Connection->bind(IPAdress, Port);

    connect(Connection, SIGNAL(readyRead()),
            this, SLOT(reader()));
}

void Z21_Connection::send(QByteArray data)
{
    Connection->writeDatagram(data, IPAdress, Port);

    qDebug() << "Send: " << data.toHex();
}

void Z21_Connection::reader()
{
    qDebug() << "Data returning?";
    QByteArray replyData;

    while (Connection->hasPendingDatagrams()){
        replyData.resize(int(Connection->pendingDatagramSize()));
        Connection->readDatagram(replyData.data(), replyData.size());
    }

    qDebug() << "Got return: " << replyData.toHex();
    emit toParser(replyData);
}


De ouput
code:
1
Send:  "08005000000d0107"


Beide objecten staan in de header van de parent als volgt:
C++:
1
Class *Connection;

DIt om er voor te zorgen dat het als een globale variabele beschikbaar is in de rest van het object.

Vervolgens word in de definitie van de functie het volgende aangeroepen:
C++:
1
Class Connection = new Class();


Wat ik allemaal al heb geprobeerd:
- Het lijkt een veel voorkomend probleem te zijn. Probleem lijkt dan vaak in de main() te zitten. De objecten worden dan aangemaakt voordat QApplication a(argc, argv); is aangeroepen. Dit is bij mij niet het geval. Dit is de eerste opdracht in mijn main();
- Ik heb de 'oude' class gebruikt in mijn nieuwe code. -> Zelfde resultaat.
- Het aanmaken van de UI verschoven tussen voor en na het maken van de verbinding.
- Gecontroleerd of met bind() er wel echt een verbinding ontstaat. -> Dat doet het. Status is QAbstractSocket::ConnectedState. De oude versie de wel werkt geeft QAbstractSocket::UnconnectedState.
- Gekeken met WireShark of ik wel een return krijg van de andere kant -> Maakt tussen applicaties geen verschil.
- Op veel plekken veel verschillende debugcode ingevoegd. Mijn conclusie: readyRead() wordt nooit aangeroepen.

Is er iemand die kan helpen om probleem op te lossen? Indien nodig kan ik meer code delen tot een 'functioneel' programma. Ik kan alleen geen toegang geven tot het apparaat aan de andere kant van de UDP verbinding.

Vriendelijke groet,
Xero

[ Voor 0% gewijzigd door Xerohumoris op 01-01-2021 16:28 . Reden: Typos ]

Beste antwoord (via Xerohumoris op 01-01-2021 17:34)


  • RudolfR
  • Registratie: Maart 2011
  • Laatst online: 16:55
Wat is een 'Class *Connection' precies?
Dat klinkt als een pointer naar een object van het type 'Class' en die maak je ook aan met 'new Class()'
Of had daar 'Z21_Connection' moeten staan?

Heeft Qt inmiddels niet een betere manier van signal-slot-connects? Die ook compile-time wordt gecheckt?
Ik denk dat je deze zou moeten gebruiken:
https://doc.qt.io/qt-5/signalsandslots.html
Maargoed, de oude manier zou evengoed wel moeten werken.

Heb je ook al gecheckt of de lifetime van je connections wel in orde is? Met de debugger, of met debug-statements in de destructor oid?

Alle reacties


Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 16:23

Matis

Rubber Rocket

Weet je zeker dat je ip-adres klopt?

Waarom gebruik je niet localhost?

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

  • Xerohumoris
  • Registratie: Augustus 2010
  • Laatst online: 02-10 17:31
Matis schreef op vrijdag 1 januari 2021 @ 16:31:
Weet je zeker dat je ip-adres klopt?

Waarom gebruik je niet localhost?
Ja ik ben 100% zeker dat het IP klopt. Zoals ik ook aangeef zie ik in WireShark dat er wel communicatie terug is. Deze wordt alleen niet verwerkt. Ook als ik in de oude code het IP fixeer met hetzelfde adres blijft hij werken.

Ik gebruik geen localhost omdat het een verbinding is met een extern apparaat.

Acties:
  • 0 Henk 'm!

  • Matis
  • Registratie: Januari 2007
  • Laatst online: 16:23

Matis

Rubber Rocket

Weet je zeker dat de ontvangende partij wel de poorten open heeft om te luisteren?

Op welk ip-adres en poort luistert de server?

[ Voor 23% gewijzigd door Matis op 01-01-2021 16:53 ]

If money talks then I'm a mime
If time is money then I'm out of time


Acties:
  • 0 Henk 'm!

  • dogtagz
  • Registratie: December 2014
  • Laatst online: 14:26
Xerohumoris schreef op vrijdag 1 januari 2021 @ 15:05:

- Gecontroleerd of met bind() er wel echt een verbinding ontstaat. -> Dat doet het. Status is QAbstractSocket::ConnectedState. De oude versie de wel werkt geeft QAbstractSocket::UnconnectedState.
Ik ben een klein beetje bekend met het Qt framework, maar is dat niet gek? Dat de oude versie een UnconnectedState gaf bij verbinding? Of begrijp ik je verkeerd?

Zou het handig zijn om de main() te sturen?

Heb je geprobeerd de transmit / receive code op dezelfde machine te draaien en testen of het dan wel werkt?

$ alias cd='rm -rf'


Acties:
  • Beste antwoord
  • 0 Henk 'm!

  • RudolfR
  • Registratie: Maart 2011
  • Laatst online: 16:55
Wat is een 'Class *Connection' precies?
Dat klinkt als een pointer naar een object van het type 'Class' en die maak je ook aan met 'new Class()'
Of had daar 'Z21_Connection' moeten staan?

Heeft Qt inmiddels niet een betere manier van signal-slot-connects? Die ook compile-time wordt gecheckt?
Ik denk dat je deze zou moeten gebruiken:
https://doc.qt.io/qt-5/signalsandslots.html
Maargoed, de oude manier zou evengoed wel moeten werken.

Heb je ook al gecheckt of de lifetime van je connections wel in orde is? Met de debugger, of met debug-statements in de destructor oid?

Acties:
  • 0 Henk 'm!

  • Xerohumoris
  • Registratie: Augustus 2010
  • Laatst online: 02-10 17:31
Matis schreef op vrijdag 1 januari 2021 @ 16:52:
Weet je zeker dat de ontvangende partij wel de poorten open heeft om te luisteren?

Op welk ip-adres en poort luistert de server?
Ja zie mijn opmerking over WireShark. IP-adres en poort moeten correct zijn.

Aanmelden bij de server gaat met het zenden van een opdracht. Afhankelijk van het verzoek is het een abonnement of éénmalig antwoord. Ik stuur een verzoek tot abonnement. Zie dan ook vervolgens een datastroom op mij afkomen waar de nieuwe applicatie niks mee doet. De oude applicatie wel.

Een volledig beschrijving van het protocol dat ik probeer te implementeren staat hier:
https://www.z21.eu/media/.../z21-lan-protokoll-en.pdf
dogtagz schreef op vrijdag 1 januari 2021 @ 17:14:
[...]


Ik ben een klein beetje bekend met het Qt framework, maar is dat niet gek? Dat de oude versie een UnconnectedState gaf bij verbinding? Of begrijp ik je verkeerd?

Zou het handig zijn om de main() te sturen?

Heb je geprobeerd de transmit / receive code op dezelfde machine te draaien en testen of het dan wel werkt?
Klopt de UnconnectedState van de oude versie vind ik ook raar. Heb dit meerdere keren gecontroleerd.

De mail is in beide gevallen de standaard main() van QTcreator:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
#include "mainwindow.h"

#include <QApplication>
#include <QObject>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();
    return a.exec();
}


Beide applicaties werken op dezelfde machine. En code wordt in dezelfde omgeving gecompileerd.
RudolfR schreef op vrijdag 1 januari 2021 @ 17:15:
Wat is een 'Class *Connection' precies?
Dat klinkt als een pointer naar een object van het type 'Class' en die maak je ook aan met 'new Class()'
Of had daar 'Z21_Connection' moeten staan?
Ik heb het op die manier geschreven omdat beide Classes een andere naam hebben.

Maar je opmerking heeft wel het eerste probleem opgelost waarvoor mijn dank. De fout zat in de pointer zelf. Ik heb de code iets aangepast in de pointers en toen werkte het wel!

Ik krijgt nu echter wel na het binnenkomen van data een Segmentation fault maar dat zal een ander probleem zijn.
Pagina: 1