Partage
  • Partager sur Facebook
  • Partager sur Twitter

Client TCP avec QT

20 mai 2019 à 15:28:10

Bonjour, j'ai un projet qui consiste à récupérer les données d'une station météo stockées dans un serveur TCP. Je dois donc réaliser une IHM avec QT qui servira également de client pour que l'affichage des données s'actualisent régulièrement.

N'ayant pas beaucoup d'expérience avec QT creator, je voulais savoir si vous pouviez m'aider en me donnant quelques bases essentielles.

J'ai déjà réalisé une première version de l'IHM dont voici une capture d'écran : 

Ici les données sont écrites "en dur", directement dans le code et ne sont donc jamais rafraîchies.

Je vous glisse également mon code si ça peut aider à mieux comprendre : 

IHM.pro

#-------------------------------------------------
#
# Project created by QtCreator 2019-01-28T14:53:16
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = IHM
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

CONFIG += c++11

SOURCES += \
        main.cpp \
        mainwindow.cpp

HEADERS += \
        mainwindow.h

FORMS += \
        mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

DISTFILES +=

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QWidget>
#include <QtWidgets>
#include <QDebug>
class MainWindow : public QWidget
{
   Q_OBJECT
public:
   explicit MainWindow(QWidget *parent = 0);

signals:

public slots:

private :
   QLabel * labelTemperature;
   QLabel * label_Temperature;
   QLabel * labelHumidity;
   QLabel * label_Humidity;
   QLabel * labelWind;
   QLabel * label_Wind;
   QLabel * titleWeather;
   QPushButton * btnSauvegarder;
   QLineEdit * lineEditTrame;
   QLabel * labelTitre;
   QLabel * labelWaterHeight;
   QLabel * label_WaterHeight;
   QGridLayout* WindowLayout;

};

#endif // MAINWINDOW_H


mainwindow.cpp

#include "mainwindow.h"

MainWindow::MainWindow(QWidget *parent) : QWidget(parent)
{
   // QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
    this->setFixedSize(500,300);
    labelTitre= new QLabel(this);
    labelTitre->setText("Gestion d'équipements \ndans un port de plaisance");
    QFont fontTitre( "Arial", 20, QFont::Bold);
    QPalette palTitre(0xb7d2ff); // définition d'une couleur
    labelTitre->setAutoFillBackground(true);
    labelTitre->setPalette(palTitre); // affecte la couleur de font au Label
    labelTitre->setFont(fontTitre);
    labelTitre->setAlignment(Qt::AlignHCenter);

    label_WaterHeight=new QLabel(this);
    label_WaterHeight->setText("2,15m");
    labelWaterHeight=new QLabel(this);
    labelWaterHeight->setText("Hauteur d'eau:");

    titleWeather= new QLabel(this);
    titleWeather->setText("☼Météo☼");
    titleWeather->setAlignment(Qt::AlignHCenter);
    QFont fontTitleWeather( "Arial", 15, QFont::Bold);
    titleWeather->setFont(fontTitleWeather);

    label_Temperature=new QLabel(this);
    label_Temperature->setText("22.6°C");
    labelTemperature=new QLabel(this);
    labelTemperature->setText("Temperature:");

    label_Humidity=new QLabel(this);
    label_Humidity->setText("33%");
    labelHumidity=new QLabel(this);
    labelHumidity->setText("Humidité:");

    label_Wind=new QLabel(this);
    label_Wind->setText("70km/h");
    labelWind=new QLabel(this);
    labelWind->setText("Vent :");

    //Définir un layout, sous forme d'une grille
    WindowLayout = new QGridLayout(this);
    WindowLayout->addWidget(labelTitre,0,0,1,5);

    WindowLayout->addWidget(labelWaterHeight, 1, 0);
    WindowLayout->addWidget(label_WaterHeight, 1, 1, 1, 4);

    WindowLayout->addWidget(titleWeather, 2, 0, 1, 5);

    WindowLayout->addWidget(label_Temperature, 3, 2);
    WindowLayout->addWidget(labelTemperature, 3, 0);

    WindowLayout->addWidget(label_Humidity, 4, 2);
    WindowLayout->addWidget(labelHumidity, 4, 0);

    WindowLayout->addWidget(label_Wind, 5, 2);
    WindowLayout->addWidget(labelWind, 5, 0);


    //connect(btnGetData, SIGNAL(clicked()), this, SLOT(GetData()));
    //connect(btnSauvegarder, SIGNAL(clicked()), this, SLOT(Sauvegarder()));

}

/*void MainWindow::GetData()
{
   QString fileName = QFileDialog::getOpenFileName(this,"Choisir fichier", "Y:\cahiersTp\BTS2\TP\TP-QT1", "Fichier textes (donc en *.txt hein)");
   QFile file(fileName);
   if(file.open(QIODevice::ReadOnly | QIODevice::Text))
   {
       QTextStream fluxTrame (&file);
       QString trame = fluxTrame.readLine();
       QStringList tabTrame = trame.split(',');
       label_WaterHeight->setText(trame);
       label_Temperature->setText(tabTrame[4] + "," + tabTrame[5]);
       lineEditAltitude->setText(tabTrame[9] + "," + tabTrame[10]);
       label_Humidity->setText(tabTrame[2] + "," + tabTrame[3]);
       lineEditnbSatellite->setText(tabTrame[7]);
   }
       file.close();
}*/





main.cpp

#include <QApplication>
#include "mainwindow.h"

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



Je reste dispo s'il faut + d'info, je vous remercie pour toute aide apportée.


  • Partager sur Facebook
  • Partager sur Twitter
20 mai 2019 à 15:32:23

https://doc.qt.io/archives/3.3/clientserver-example.html

Si tu veux regarder plus en détails, la documentation QT est assez bien faite ;)

-
Edité par Didy7 20 mai 2019 à 15:35:23

  • Partager sur Facebook
  • Partager sur Twitter
3 juin 2019 à 22:42:21

Bonsoir, 

je viens d'exécuter le code suivant qui est sensé envoyer message à mon serveur tcp mais je ne reçoit rien du tout, je ne sais même pas si le message est bien envoyé :/

//Creation socket
QTcpSocket socMeteo;
socMeteo.connectToHost("192.168.1.35",10001);
//Envoi de donnees
QTextStream texte(&socHauteur);
//texte<<phrase<<endl;
texte<<"Bonsoir"<<endl;

Le serveur tcp est bien fonctionnel mais aucun message reçu ! Qu'est-ce que j'ai bien pu oublié svp ?

  • Partager sur Facebook
  • Partager sur Twitter
4 juin 2019 à 22:05:19

Salut,

Je n'aime pas trop QT pour tout ce qui n'est pas graphique , la partie réseau tourne en même temps que le graphique donc si tu n'as pas lancé le thread principal de QT  

QApplication app(argc, argv);
//code
return app.exec();

Il attendra d'être à la fonction Exec pour effectivement lancer la requête c'est pour ça qu'il faut lui forcer la main .

un exemple pour lui envoyer un message :

#include <QTcpSocket>

int main(int argc, char *argv[]) {
    
    QTcpSocket *socket = new QTcpSocket();
	
    socket->connectToHost("192.168.0.1", 4321);
    if(!socket->waitForConnected(1000)){
        return 1;
    }
    
    socket->write(QString("text").toLatin1());
    if(!socket->waitForBytesWritten(100)){
        return 2;
    }
    return 0;
}

En espérant que cela a résolu ton problème :)




-
Edité par di20 4 juin 2019 à 22:05:58

  • Partager sur Facebook
  • Partager sur Twitter
5 juin 2019 à 14:40:08

Salut,

merci de ta réponse, j'ai mis ton code dans le .cpp de mon IHM (pas dans le main) en commentant les return et je reçois donc bien un message sur mon serveur. Donc si je comprends bien, "write" sers à envoyer vers le serveur. Sachant que celui-ci doit renvoyer une chaine de caractères au client, est-ce qu'il existe un membre du genre "listen" qui pourrait recevoir cette chaine de caractères et la stocker dans une variable ?

  • Partager sur Facebook
  • Partager sur Twitter
5 juin 2019 à 20:52:43

Tu devrais regarder la doc.

Pour attendre la réception de données, sans utiliser la gestion des événements, c'est la fonction waitForReadyread qu'il te faudra utiliser.

-
Edité par zoup 5 juin 2019 à 20:52:56

  • Partager sur Facebook
  • Partager sur Twitter
5 juin 2019 à 22:57:59

Merci pour ta réponse. Aurait-tu un exemple simple de cette fonction à me fournir pour pouvoir l'intégrer à mon programme ?
  • Partager sur Facebook
  • Partager sur Twitter
6 juin 2019 à 0:38:13

Je t'ai demandé de lire la doc. Tu n'as pas du le faire parce qu'elle contient justement l'exemple simple que tu cherches.

La consultation des docs de référence est un passage obligé si tu veux progresser.

  • Partager sur Facebook
  • Partager sur Twitter
6 juin 2019 à 1:34:47

Oui oui j'ai lu plusieurs docs bien avant de poster mon premier message (https://doc.qt.io/qt-5/qtcpsocket.html et https://doc.qt.io/qt-5/qtcpsocket-members.html) mais j'ai un peu de mal à comprendre ces exemples justement, notamment pour appeler les fonctions et les paramètre que je dois y mettre. J'ai pourtant essayé d'utiliser waitForReadyRead mais j'ai l'impression de ne pas avoir la bonne syntaxe en faisant 
    trame = socket->waitForReadyRead();
J'essaie juste de récupérer la réponse du serveur pour le stocker dans une variable
  • Partager sur Facebook
  • Partager sur Twitter
6 juin 2019 à 14:02:50

socket->waitForReadyRead();

ne te renvoie pas les données du buffer de réception, mais un simple booléen indiquant que des données ont été reçues: "The function returns true if the readyRead() signal is emitted and there is new data available for reading".

Pour lire les données, il faut utiliser read, readData ou readAll.

  • Partager sur Facebook
  • Partager sur Twitter