Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. International
  3. French
  4. Problème avec pthread et QPlainTextEdit
Forum Updated to NodeBB v4.3 + New Features

Problème avec pthread et QPlainTextEdit

Scheduled Pinned Locked Moved Unsolved French
16 Posts 5 Posters 1.7k Views 3 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Mourad2021
    wrote on last edited by
    #1

    J’ai réalisé un petit programme Client-Serveur sou Qt mais en utilisant pthread pour permettre une indépendance du Framework Qt et surtout pour la portabilité.
    Voici les fichiers Du serveur :
    Fichier header.h : ce fichire contient les inclusions communes et quelques define

    #ifndef HEADER_H
    #define HEADER_H
    
    // On inclut les fichiers standards
    #include <iostream>
    #include <stdlib.h>
    #include <stdio.h>
    #include <pthread.h>
    #include <thread>
    #include <mutex>
    
    //Les Fichiers Qt
    #include <QPlainTextEdit>
    #include <QPushButton>
    
    #define PORT 10000
    
    #if defined (WIN32) //Si nous sommes sous WINDOWS
          #include <winsock2.h>
          #include <windows.h>
          //On peut remarquer que le type socklen_t qui existe sous Linux, n'est pas défini sous Windows. Ce type sert à stocker la taille d'une structures de type sockaddr_in. Ça n'est rien d'autre qu'un entier mais il nous évitera des problèmes éventuels de compilation sous Linux par la suite. Il va donc falloir le définir nous même à l'aide du mot clef typedef comme il suit
          typedef int socklen_t;
    
    #elif defined (linux) //Si nous sommes sous LINUX
          #include <sys/types.h>
          #include <sys/socket.h>
          #include <netinet/in.h>
          #include <arpa/inet.h>
          #include <unistd.h>
    
          // Define, qui nous serviront par la suite
          #define INVALID_SOCKET -1
          #define SOCKET_ERROR -1
          #define closesocket(s) close(s)
    
          // De même
          typedef int SOCKET;
          typedef struct sockaddr_in SOCKADDR_IN;
          typedef struct sockaddr SOCKADDR;
    #endif
    
    struct Shared
    {
          int data;
          pthread_mutex_t mut;
          pthread_cond_t synchro;
    };
    
    struct ThreadData
    {
          QPlainTextEdit *strucPlainText;
          QPushButton *strucBtnOn;
          QPushButton *strucBtnOff;
          struct Shared *psh;
    };
    
    struct MsgData
    {
          char nom[256];
          char message[256];
    };
    
    #endif // HEADER_H
    

    Le fichier classserver.h

    #ifndef CLASSSERVER_H
    #define CLASSSERVER_H
    
    #include "header.h"
    #include <QDebug>
    #include <QPlainTextEdit>
    #include <QString>
    
    class ClassServer
    {
    
    private:
          unsigned temp = GetConsoleOutputCP();
          /* Socket et contexte d'adressage du serveur  */
          static SOCKET sock;
          static SOCKADDR_IN sin;
          static socklen_t recsize;
    
          /* Socket et contexte d'adressage du client */
          static SOCKET csock;
          static SOCKADDR_IN csin;
          static socklen_t crecsize;
          static int sock_err;
    
          static QPlainTextEdit *m_plainTextEdit ;
          static struct ThreadData m_threadData;
          static bool m_graphic;
          static struct MsgData m_msgDataServer;
    
    
    public:
          ClassServer();
          ClassServer(struct ThreadData &myThreadData);
          ~ClassServer();
          static bool Initialisation();
          static void* FctListenClient(void *);
          static void FctSendMessage(struct MsgData &);
          static bool FctDeconnect();
    };
    
    #endif // CLASSSERVER_H
    

    Le fichier classserver.cpp

    #include "classserver.h"
    
    SOCKET ClassServer::sock = 0;
    SOCKADDR_IN ClassServer::sin;
    socklen_t ClassServer::recsize = sizeof(sin);
    
    SOCKET ClassServer::csock = 0;
    SOCKADDR_IN ClassServer::csin =SOCKADDR_IN();
    socklen_t ClassServer::crecsize = sizeof(csin);
    int ClassServer::sock_err = 0;
    
    QPlainTextEdit* ClassServer::m_plainTextEdit = nullptr;
    struct ThreadData ClassServer::m_threadData;
    bool ClassServer::m_graphic = false;
    struct MsgData ClassServer::m_msgDataServer;
    
    
    //Constructeur par défaut
    ClassServer::ClassServer()
    {
          m_graphic = false;
    }
    
    
    //Constructeur avec la structure comme parametre
    ClassServer::ClassServer(struct ThreadData &myThreadData)
    {
          m_graphic = true;
          m_threadData = myThreadData;
    }
    
    bool ClassServer::Initialisation()
    {
          SetConsoleOutputCP(CP_UTF8);
          //Si nous sommes sous WINDOWS
          int erreur;
    
    #if defined (WIN32)
          //De plus, on doit  devrez ajouter, dans le début de notre fonction main, le code suivant pour pouvoir utiliser les sockets sous Windows
          WSADATA WSAData;
          //La fonction WSAStartup sert à initialiser la bibliothèque WinSock. La macro MAKEWORD transforme les deux entiers (d'un octet) qui lui sont passés en paramètres en un seul entier (de 2 octets) qu'elle retourne. Cet entier sert à renseigner la bibliothèque sur la version que l'utilisateur souhaite utiliser (ici la version 2,0). Elle retourne la valeur 0 si tout s'est bien passé
          erreur = WSAStartup(MAKEWORD(2,2), &WSAData);
    #elif
          erreur = 0;
    #endif
    
          bool retVal = false;
          if(!erreur)
          {
                // 1------------------------------------------------ Création de la socket------------------------------------------------//
    
                /*Pour créer la socket, il nous faudra utiliser la fonction socket avec le prototype suivant :
           * int socket(int domain, int type, int protocol);*/
    
    
                //Comme dans notre cas nous utiliserons le protocole TCP/IP, notre fonction sera toujours :
                sock = socket(AF_INET, SOCK_STREAM, 0);
                // Si la socket est valide
                if(sock != INVALID_SOCKET)
                {
                      if(!m_graphic)
                            printf("La socket %d est maintenant ouverte en mode TCP/IP\n", (unsigned int)sock);
                      else
                      {
                            pthread_mutex_lock(&m_threadData.psh->mut);
                            m_threadData.strucPlainText->appendPlainText(QString("La socket %1 est maintenant ouverte en mode TCP/IP\n").arg((unsigned int)sock));
                            pthread_mutex_unlock(&m_threadData.psh->mut);
                      }
    
                      // 2------------------------------------------------Paramétrer une socket------------------------------------------------//
    
                      /* Après avoir déclaré et créé la socket, nous allons la paramétrer */
                      /* Configuration */
                      // SOCKADDR_IN sin; //Déja créée ci-dessus
                      sin.sin_family = AF_INET;
                      sin.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
                      sin.sin_port = htons(PORT);
                      retVal = true;
                }
                else
                {
                      if(!m_graphic)
                            perror("socket");
                      else
                      {
                            pthread_mutex_lock(&m_threadData.psh->mut);
                            m_threadData.strucPlainText->appendPlainText(QString("Erreur Socket :  %1 ").arg(GetLastError()));
                            pthread_mutex_unlock(&m_threadData.psh->mut);
                      }
                }
          }
          return retVal;
    }
    
    
    //Déstructeur
    ClassServer::~ClassServer()
    {
          SetConsoleOutputCP(temp);
    }
    
    //La fonction LISTEN
    void* ClassServer::FctListenClient(void *arg)
    {
          // 3------------------------------------------------Établir une connexion avec le client*------------------------------------------------//
    
          /*Enfin, pour associer à la socket ces informations, nous allons utiliser la fonction :
           * int bint(int socket, const struct sockaddr* addr, socklen_t addrlen); */
    
          (void *)arg;
          int theStatus = 1;
          //Donc, nous ferons toujours ainsi :
          sock_err = bind(sock, (SOCKADDR *)&sin, recsize);
          /* Si la socket ne fonctionne pas*/
          if(sock_err == SOCKET_ERROR)
          {
                //On appelle la fonction FctThreadListenClient
                if(m_graphic)
                {
                      //pthread_mutex_lock(&m_threadData.psh->mut);
                      m_threadData.strucPlainText->appendPlainText(QString("Erreur : bind :  %1 ").arg(GetLastError()));
                      //pthread_mutex_unlock(&m_threadData.psh->mut);
                }
          }
          /* Si la socket fonctionne */
          else
          {
    
                // 4------------------------------------------------Établir une ecoute avec le client------------------------------------------------//
                //Démarrage du listage (mode server)
                bool stopWhile = true;
    
    
                sock_err = listen(sock, 5);
                qDebug() << " sock_err = " << sock_err;
                if(m_graphic)
                {
                      m_threadData.strucPlainText->appendPlainText(QString("Listage du port %1...\n").arg(PORT));
                }
    
                /* Si la socket fonctionne en LISTEN*/
                if(sock_err != SOCKET_ERROR)
                {
                      // On utilisera la fonction comme cela :
                      // Attente pendant laquelle le client se connecte
                      if(m_graphic)
                      {
                            m_threadData.strucPlainText->appendPlainText(QString("Patientez pendant que le client se connecte sur le port %1 ").arg(PORT));
                      }
                      while(stopWhile)
                      {
                            csock = accept(sock, (SOCKADDR*)&csin, &crecsize); //Avec "csock" représentant la socket client et "csin" son contexte d'adressage.
                            //Si CSOCK est une invalide socket
                            if(csock == INVALID_SOCKET)
                            {
                                  if(m_graphic)
                                  {
                                        //pthread_mutex_lock(&m_threadData.psh->mut);
                                        m_threadData.strucPlainText->appendPlainText(QString("Problème de création de socket client"));
                                        //pthread_mutex_unlock(&m_threadData.psh->mut);
                                  }
                                  stopWhile = false;
                            }
                            //Si CSOCK est une valide socket
                            else
                            {
    
                                  if(m_graphic)
                                  {
                                        m_threadData.strucPlainText->appendPlainText(QString("Un client se connecte avec la socket %1 de %2 : %3\n").arg((int)csock).arg(inet_ntoa(csin.sin_addr)).arg(htons(csin.sin_port)));
                                  }
                            } /* Si CSOCK est une valide socket */
                      } /*  la boucle WHILE */
                }
                /* Si la socket ne fonctionne pas en LISTEN*/
                else
                {
                      if(m_graphic)
                      {
                            m_threadData.strucPlainText->appendPlainText(QString("Erreur Listen"));
                      }
                }
                void *retval = nullptr;
    
          }/* Si la socket fonctionne */
          //return nullptr;
          pthread_exit((void*)(theStatus));
    }
    
    void ClassServer::FctSendMessage(struct MsgData &msgData)
    {
          sock_err = send(csock, (char*)&msgData, sizeof(msgData), 0);
          if(sock_err != SOCKET_ERROR )
          {
                qDebug() << "Le message a bien était envoyé";
          }
          else
          {
                qDebug() << "Le message n'a pas était envoyé";
          }
    }
    
    bool ClassServer::FctDeconnect()
    {
          // 4------------------------------------------------Fermer la connexion------------------------------------------------//
          /*Finalement nous terminerons par la fonction closesocket qui permet de fermer une socket.
          * int closesocket(int sock);
          * Son prototype est très simple, je pense donc que la fonction se passe de commentaires.*/
          //Fermeture de la socket client et de la socket serveur
    
    
          bool retVal = false;
          //Fermeture de la socket client
          qDebug() << "csock in deconnect = " << csock;
          if(csock != INVALID_SOCKET)
          {
                if(!closesocket(csock))
                {
                      if(m_graphic)
                      {
                            //pthread_mutex_lock(&m_threadData.psh->mut);
                            m_threadData.strucPlainText->appendPlainText("Fermeture de la socket client.");
                            //pthread_mutex_unlock(&m_threadData.psh->mut);
                      }
    
                      retVal = true;
                }
                else
                {
                      if(m_graphic)
                      {
                            //pthread_mutex_lock(&m_threadData.psh->mut);
                            m_threadData.strucPlainText->appendPlainText("La socket client n'a pas été fermée.");
                            //pthread_mutex_unlock(&m_threadData.psh->mut);
                      }
    
                      retVal = false;
                }
          }
    
          //Fermeture de la socket serveur
          if(!closesocket(sock))
          {
                if(m_graphic)
                {
                      //pthread_mutex_lock(&m_threadData.psh->mut);
                      m_threadData.strucPlainText->appendPlainText("Fermeture de la socket serveur.");
                      //pthread_mutex_unlock(&m_threadData.psh->mut);
                }
    
                retVal = true;
          }
          else
          {
                if(m_graphic)
                {
                      //pthread_mutex_lock(&m_threadData.psh->mut);
                      m_threadData.strucPlainText->appendPlainText("La socket serveur n'a pas été fermée.");
                      //pthread_mutex_unlock(&m_threadData.psh->mut);
                }
    
                retVal = false;
          }
    
          if(!m_graphic)
          {
                m_threadData.strucPlainText->appendPlainText("Fermeture du serveur terminée.");
          }
    
          //Si nous sommes sous WINDOWS
    #if defined (WIN32)
          //Cette fonction va simplement libérer les ressources allouées par la fonction WSAStartup().
          WSACleanup();
    #endif
          return retVal;
    }
    

    Ensuite voici le mainwindowserver.h

    #ifndef MAINWINDOWSERVER_H
    #define MAINWINDOWSERVER_H
    
    #include <QMainWindow>
    #include <QMessageBox>
    #include "threadFunctions.h"
    
    namespace Ui {
          class MainWindowServer;
    }
    
    class MainWindowServer : public QMainWindow
    {
          Q_OBJECT
    
    public:
          explicit MainWindowServer(QWidget *parent = nullptr);
          ~MainWindowServer();
          void FctConnections();
    
    public slots:
          void SlotStartServer();
          void SlotSendMessage();
          void SlotDeconnexion();
    
    
    private:
          Ui::MainWindowServer *ui;
          ClassServer myClassServer;
          //On déclare les thread
          pthread_t threadListen;
          struct Shared m_shared;
          struct ThreadData m_threadData;
          struct MsgData m_msgDataServer;
    
    };
    
    #endif // MAINWINDOWSERVER_H
    

    voici le fichier mainwindowserver.cpp

    #include "mainwindowserver.h"
    #include "ui_mainwindowserver.h"
    
    MainWindowServer::MainWindowServer(QWidget *parent) :
          QMainWindow(parent),
          ui(new Ui::MainWindowServer)
    {
          ui->setupUi(this);
          m_shared =
          {
                .data = 0,
                .mut = PTHREAD_MUTEX_INITIALIZER,
                .synchro = PTHREAD_COND_INITIALIZER,
          };
    
          m_threadData =
          {
                .strucPlainText = ui->plainTextEditRapport,
                .strucBtnOn = ui->btnLancer,
                .strucBtnOff = ui->btnDeconnecter,
                .psh = &m_shared,
          };
    
          FctConnections();
    }
    
    MainWindowServer::~MainWindowServer()
    {
          pthread_cancel(threadListen);
          delete ui;
          //delete myClassServer;
    }
    
    void MainWindowServer::FctConnections()
    {
          QObject::connect(ui->btnLancer, SIGNAL(clicked()), this, SLOT(SlotStartServer()));
          QObject::connect(ui->btnDeconnecter, SIGNAL(clicked()), this, SLOT(SlotDeconnexion()));
          QObject::connect(ui->btnEnvoyer, SIGNAL(clicked()), this, SLOT(SlotSendMessage()));
    }
    
    void MainWindowServer::SlotStartServer()
    {
          //myClassServer = ClassServer((QPlainTextEdit*)ui->plainTextEditRapport);
    myClassServer = ClassServer(m_threadData);
    
          if(myClassServer.Initialisation())
          {
                //Lancement de l'écoute du serveur
                int ret =  pthread_create(&threadListen, NULL, ClassServer::FctListenClient, nullptr);
                if(ret != 0) {
                      ui->plainTextEditRapport->appendPlainText("Erreur : erreur de création de pthread_create().");
                }
                else
                {
                      ui->plainTextEditRapport->appendPlainText("Succés : Création de pthread réussie");
                      ui->btnLancer->setEnabled(false);
                      ui->btnDeconnecter->setEnabled(true);
                }
          }
    }
    
    void MainWindowServer::SlotSendMessage()
    {
          strcpy(m_msgDataServer.nom, "Serveur");
          strcpy(m_msgDataServer.message, ui->lineEditMessage->text().toStdString().c_str());
          ClassServer::FctSendMessage(m_msgDataServer);
    }
    
    void MainWindowServer::SlotDeconnexion()
    {
    
          //pthread_cancel(threadListen);
          if(myClassServer.FctDeconnect())
          {
                ui->btnDeconnecter->setEnabled(false);
                ui->btnLancer->setEnabled(true);
          }
    
          //Just pour tester l'arret du thread
          if(pthread_cancel(threadListen))
                qDebug() << "threadListen arreter";
          else
                qDebug() << "threadListen pas arreter";
    }
    

    Enfin voici le main.cpp pas grande chose dedans

    #include "mainwindowserver.h"
    
    #include <QApplication>
    #include <QLocale>
    #include <QTranslator>
    
    int main(int argc, char *argv[])
    {
          QApplication a(argc, argv);
    
          QTranslator translator;
          const QStringList uiLanguages = QLocale::system().uiLanguages();
          for (const QString &locale : uiLanguages) {
                const QString baseName = "SocketGraphicServer_" + QLocale(locale).name();
                if (translator.load(":/i18n/" + baseName)) {
                      a.installTranslator(&translator);
                      break;
                }
          }
          MainWindowServer w;
          w.show();
          return a.exec();
    }
    

    /*******************************************************************************/
    Maintenant voici les fichiers Du côté client

    Fichier classclient.h

    #ifndef CLASSCLIENT_H
    #define CLASSCLIENT_H
    
    #include "../SocketGraphicServer/header.h"
    #include <QDebug>
    #include <QPlainTextEdit>
    #include <QString>
    #include <QMessageBox>
    
    class ClassClient
    {
          unsigned temp = GetConsoleOutputCP();
          /* Socket et contexte d'adressage du client */
          static SOCKET csock;
          static SOCKADDR_IN csin;
          static socklen_t crecsize;
          static int sock_err;
    
          static QPlainTextEdit *m_plainTextEdit ;
          static struct ThreadData m_threadDataClient;
          static bool m_graphic;
          static struct MsgData m_msgDataClient;
          static bool boolConnection;
    
    public:
          ClassClient();
          ClassClient(struct ThreadData &myThreadData);
          ~ClassClient();
          static void Initialisation();
          static bool FctConnection();
          static void FctDeconnection();
          static void* FctReceiveMsg(void*);
    };
    
    #endif // CLASSCLIENT_H
    

    Fichier classclient.cpp

    #include "classclient.h"
    
    SOCKET ClassClient::csock = 0;
    SOCKADDR_IN ClassClient::csin;
    socklen_t  ClassClient::crecsize = sizeof(csin);
    int  ClassClient::sock_err;
    
    QPlainTextEdit *m_plainTextEdit = nullptr ;
    struct ThreadData ClassClient::m_threadDataClient;
    bool ClassClient::m_graphic = false;
    struct MsgData ClassClient::m_msgDataClient;
    bool ClassClient::boolConnection = false;
    
    ClassClient::ClassClient()
    {
          m_graphic = false;
          Initialisation();
    }
    
    ClassClient::ClassClient(struct ThreadData &myThreadData)
    {
          m_graphic = true;
          m_threadDataClient = myThreadData;
    
          Initialisation();
    }
    
    ClassClient::~ClassClient()
    {
          SetConsoleOutputCP(temp);
    }
    
    void ClassClient::Initialisation()
    {
          SetConsoleOutputCP(CP_UTF8);
    #if defined (WIN32)
          WSADATA WSAData;
          int erreur = WSAStartup(MAKEWORD(2,2), &WSAData);
    #elif
          int erreur = 0;
    #endif
    
          if(!erreur)
          {
                /* Création de la socket */
                csock = socket(AF_INET, SOCK_STREAM, 0);
                printf("La socket client est %d\n", csock);
                /* Configuration de la connexion */
                csin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //127.0.0.1"); "192.168.0.12"
                csin.sin_family = AF_INET;
                csin.sin_port = htons(PORT);
          }
    }
    
    bool ClassClient::FctConnection()
    {
          m_threadDataClient.strucPlainText->appendPlainText(QString("je suis la connection"));
          bool returnVal = false;
    
          //Si on n'arrive pas à se connecter.
          if(connect(csock, (SOCKADDR *)&csin, sizeof(csin)) == SOCKET_ERROR)
          {
                //printf("Connexion à %s sur le port %d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
                // Attente pendant laquelle le client se connecte
                if(!m_graphic)
                      printf("Impossible de se connecter.");
                else
                      m_threadDataClient.strucPlainText->appendPlainText(QString("Impossible de se connecter."));
                returnVal = false;
          }
          //Si on arrive à se connecter
          else
          {
                if(!m_graphic)
                      printf("Connexion à %s sur le port %d\n", inet_ntoa(csin.sin_addr), htons(csin.sin_port));
                else
                {
                      m_threadDataClient.strucPlainText->appendPlainText(QString("Connexion à %1 sur le port %2.").arg(inet_ntoa(csin.sin_addr)).arg(htons(csin.sin_port)));
                }
    
                returnVal = true;
                boolConnection = true;
          }
    
          return returnVal;
    }
    
    void ClassClient::FctDeconnection()
    {
          /* On ferme la socket précédemment ouverte */
          closesocket(csock);
          //QMessageBox::information(nullptr, "csock", QString::number(csock));
    
    #if defined (WIN32)
          WSACleanup();
    #endif
          boolConnection = false;
          m_threadDataClient.strucPlainText->appendPlainText(QString("Déconnexion"));
    }
    
    void* ClassClient::FctReceiveMsg(void *arg)
    {
          qDebug() << "j'attends un message avant le while" ;
          //m_msgDataClient = (MsgData*)arg;
          while(boolConnection)
          {
                if(recv(csock, (char*)&m_msgDataClient, sizeof(m_msgDataClient), 0) != SOCKET_ERROR)
                {
    
                      std::string nom = m_msgDataClient.nom;
                      std::string message = m_msgDataClient.message;
                      qDebug() << QString::fromStdString(nom);
                      qDebug() << QString::fromStdString(message);
                       if(!m_graphic)
                             printf("Connexion à %s sur le port %d\n", inet_ntoa(csin.sin_addr), htons(csin.sin_port));
                       else
                       {
                             pthread_mutex_lock(&m_threadDataClient.psh->mut);
                             m_threadDataClient.strucPlainText->appendPlainText(QString(QString::fromStdString(nom) + " : " + QString::fromStdString(message)));
                             pthread_mutex_unlock(&m_threadDataClient.psh->mut);
                       }
                }
          }
          //On arrete le thread
          //pthread_exit(arg);
    }
    

    Fichier mainwindowclient.h

    #ifndef MAINWINDOWCLIENT_H
    #define MAINWINDOWCLIENT_H
    
    #include <QMainWindow>
    #include "threadFunctions.h"
    
    QT_BEGIN_NAMESPACE
    namespace Ui { class MainWindowClient; }
    QT_END_NAMESPACE
    
    class MainWindowClient : public QMainWindow
    {
          Q_OBJECT
    
    public:
          MainWindowClient(QWidget *parent = nullptr);
          ~MainWindowClient();
          void FctConnectionsObjets();
          void FctRcvMsg();
    
    public slots:
          void SlotRcvMsg();
          void SlotConnection();
          void SlotDeconnexion();
    
    private:
          Ui::MainWindowClient *ui;
          ClassClient myClassClient;
          //On déclare les thread
          pthread_t threadRcvMsg;
          //Les structures
          struct Shared m_shared;
          struct ThreadData m_threadDataClient;
    };
    #endif // MAINWINDOWCLIENT_H
    

    Le fichier mainwindowclient.cpp

    #include "mainwindowclient.h"
    #include "ui_mainwindowclient.h"
    
    MainWindowClient::MainWindowClient(QWidget *parent)
          : QMainWindow(parent)
          , ui(new Ui::MainWindowClient)
    {
          ui->setupUi(this);
          qDebug() << "entrée du constructeur";
          m_shared =
          {
                .data = 0,
                .mut = PTHREAD_MUTEX_INITIALIZER,
                .synchro = PTHREAD_COND_INITIALIZER,
          };
    
          m_threadDataClient =
          {
                .strucPlainText = ui->plainTextEditRapport,
                .strucBtnOn = ui->btnConDecon,
                .strucBtnOff = ui->btnDeconnecter,
                .psh = &m_shared,
          };
    
          myClassClient = ClassClient(m_threadDataClient);
          FctConnectionsObjets();
    }
    
    MainWindowClient::~MainWindowClient()
    {
          delete ui;
    }
    
    void MainWindowClient::FctConnectionsObjets()
    {
          QObject::connect(ui->btnConDecon, SIGNAL(clicked()), this, SLOT(SlotConnection()));
          QObject::connect(ui->btnDeconnecter, SIGNAL(clicked()), this, SLOT(SlotDeconnexion()));
    }
    
    void MainWindowClient::SlotConnection()
    {
          //myClassClient = ClassClient(m_threadDataClient);
          if(myClassClient.FctConnection())
          {
                ui->btnConDecon->setText("&Déconnecter");
                SlotRcvMsg();
          }
    
    }
    
    void MainWindowClient::SlotRcvMsg()
    {
          int ret =  pthread_create(&threadRcvMsg, NULL, ClassClient::FctReceiveMsg, nullptr);
          if(ret != 0) {
                ui->plainTextEditRapport->appendPlainText("Erreur : erreur de création de pthread_create() de \"threadRcvMsg\".");
          }
          else
          {
                ui->plainTextEditRapport->appendPlainText("Succés : Création de pthread \"threadRcvMsg\" réussie");
          }
    }
    
    void MainWindowClient::SlotDeconnexion()
    {
          ui->btnConDecon->setText("&Connecter");
          myClassClient.FctDeconnection();
    }
    

    Fichier main.cpp côté client

    #include "mainwindowclient.h"
    
    #include <QApplication>
    #include <QLocale>
    #include <QTranslator>
    
    int main(int argc, char *argv[])
    {
          QApplication a(argc, argv);
    
          QTranslator translator;
          const QStringList uiLanguages = QLocale::system().uiLanguages();
          for (const QString &locale : uiLanguages) {
                const QString baseName = "SocketGraphicClient_" + QLocale(locale).name();
                if (translator.load(":/i18n/" + baseName)) {
                      a.installTranslator(&translator);
                      break;
                }
          }
          MainWindowClient w;
          w.show();
          return a.exec();
    }
    

    Et voici mes 2 problèmes :
    Problème 1 :
    Je lance le serveur je me connecte et je peux envoyer des messages,
    Le souci c’est du coté du client que lui reçoit les messages et j’arrive à les affichés avec des qDebug() avec cette fonction coté client

    void* ClassClient::FctReceiveMsg(void *arg)
    {
          qDebug() << "j'attends un message avant le while" ;
          //m_msgDataClient = (MsgData*)arg;
          while(boolConnection)
          {
                if(recv(csock, (char*)&m_msgDataClient, sizeof(m_msgDataClient), 0) != SOCKET_ERROR)
                {
    
                      std::string nom = m_msgDataClient.nom;
                      std::string message = m_msgDataClient.message;
                      qDebug() << QString::fromStdString(nom);
                      qDebug() << QString::fromStdString(message);
                       if(!m_graphic)
                             printf("Connexion à %s sur le port %d\n", inet_ntoa(csin.sin_addr), htons(csin.sin_port));
                       else
                       {
                             pthread_mutex_lock(&m_threadDataClient.psh->mut);
                             m_threadDataClient.strucPlainText->appendPlainText(QString(QString::fromStdString(nom) + " : " + QString::fromStdString(message)));
                             pthread_mutex_unlock(&m_threadDataClient.psh->mut);
                       }
                }
          }
          //On arrete le thread
          //pthread_exit(arg);
    }
    

    Mais quand j’essaye de les affichés avec

    m_threadDataClient.strucPlainText->appendPlainText(QString(QString::fromStdString(nom) + " : " + QString::fromStdString(message)));
                             pthread_mutex_unlock(&m_threadDataClient.psh->mut);
    

    le programme crash avec cette erreur

    D:/Fichiers_applications/C++/Projets_QtCreator/Test/Revis_gnrle/Travaux_pratiques/SocketGraphic/build-SocketGraphicRoot-Desktop_Qt_6_3_1_MinGW_64_bit-Debug/SocketGraphicClient/debug/SocketGraphicClient.exe crashed.
    

    Pourtant le

    m_threadDataClient.strucPlainText->appendPlainText(QString("Déconnexion"));
    

    est utilisé dans les autres fonctions et qui marche très bien, comme dans cette fonction.

    void ClassClient::FctDeconnection()
    {
          /* On ferme la socket précédemment ouverte */
          closesocket(csock);
          //QMessageBox::information(nullptr, "csock", QString::number(csock));
    
    #if defined (WIN32)
          WSACleanup();
    #endif
          boolConnection = false;
          m_threadDataClient.strucPlainText->appendPlainText(QString("Déconnexion"));
    }
    

    Je n’arrive pas à trouver pourquoi ça crash?

    Mon deuxième problème est que :
    Quand je connecte le serveur avec cette fonction

    void MainWindowServer::SlotStartServer()
    {
          //myClassServer = ClassServer((QPlainTextEdit*)ui->plainTextEditRapport);
    myClassServer = ClassServer(m_threadData);
    
          if(myClassServer.Initialisation())
          {
                //Lancement de l'écoute du serveur
                int ret =  pthread_create(&threadListen, NULL, ClassServer::FctListenClient, nullptr);
                if(ret != 0) {
                      ui->plainTextEditRapport->appendPlainText("Erreur : erreur de création de pthread_create().");
                }
                else
                {
                      ui->plainTextEditRapport->appendPlainText("Succés : Création de pthread réussie");
                      ui->btnLancer->setEnabled(false);
                      ui->btnDeconnecter->setEnabled(true);
                }
          }
    }
    

    Et que je me déconnecte avec cette fonction

    void MainWindowServer::SlotDeconnexion()
    {
    
          //pthread_cancel(threadListen);
          if(myClassServer.FctDeconnect())
          {
                ui->btnDeconnecter->setEnabled(false);
                ui->btnLancer->setEnabled(true);
          }
    
          //Just pour tester l'arret du thread
          if(pthread_cancel(threadListen))
                qDebug() << "threadListen arreter";
          else
                qDebug() << "threadListen pas arreter";
    }
    

    La première fois se passe très bien, mais si je me déconnecte et que j’essaye de me reconnecter plus de deux fois ça crash aussi.
    Merci d’avance de votre aide je coince depuis une semaine.
    Merci à tous.

    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Bonjour et bienvenu sur devnet,

      La première règle enfreinte: ne jamais accéder à des éléments de la GUI depuis un autre thread que celui où la QApplication a été créée.

      Ensuite, par curiosité, pourquoi éliminer d'une application Qt des classes comme QTcpServer et QTcpSocket ou encore QThread, pour finalement réimplémenter leur fonctionnalité sur chaque plateforme ?

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      1
      • M Offline
        M Offline
        Mourad2021
        wrote on last edited by
        #3

        Bonjour SGaist,
        Merci de me répondre.
        En fait ça m'est t'arrivé de travailler dans des entreprises (une banque par exemple), où il ne travaille pas avec des Frameworks en général et Qt en particulier. c'est pour cette raison que j'ai choisi pthread. en général il font du développement pour de l'embarqué donc on ne peut même pas utiliser thread du c++11(bibliothèque standard).
        Et pour ce qui est l'accès à des éléments de la GUI depuis un autre thread que celui où la QApplication a été créée, c'est que je n'ai pas vraiment le choix. parce que pthread n'accepte pas les fonction membres d'une classe.
        Merci de tes éclaircissements.

        1 Reply Last reply
        0
        • SGaistS Offline
          SGaistS Offline
          SGaist
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Il faut savoir séparer les choses. Appliquer les règles du développement sur système embarqué à une application desktop n'est pas la meilleure des idées. L'inverse est tout autant vrai.

          Ce n'est pas parce que pthread n'est pas capable de faire une chose qu'il faut utiliser une alternative qui est explicitement interdite. Dans ce cas précis, il faut utiliser QMetaObject::invokeMethod.

          Ceci étant, comme dit précédemment, c'est ajouter une grosse couche de complexité pour un bénéfice de 0.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          1 Reply Last reply
          0
          • M Offline
            M Offline
            Mourad2021
            wrote on last edited by
            #5

            Bonjour SGaïste,
            En fait tout ce que j'essaye de faire c'est d'utiliser des thread indépendamment de Qt.
            je suis en train de tester une nouvelle méthode avec thread de la bibliothèque standard du c++11, je te tiendrai au courant dès que je l'aurai peaufiner. et merci encore .

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              Alors il faut garder de manière bien séparée la partie GUI et la partie thread.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              1 Reply Last reply
              0
              • M Offline
                M Offline
                Mourad2021
                wrote on last edited by
                #7

                tu veux dire que je dois mettre les fonctions utilisées dans les thread dans une classe à part ?

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  En principe, l'encapsulation est la meilleure méthode.

                  Un exemple avec QThread est Mandelbrot. Tout le processing se fait dans le thread, les données sont ensuite envoyées au thread principal pour affichage.

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply
                  0
                  • D Offline
                    D Offline
                    dan1973
                    wrote on last edited by
                    #9

                    how do i get it translated in English

                    JonBJ 1 Reply Last reply
                    0
                    • D dan1973

                      how do i get it translated in English

                      JonBJ Offline
                      JonBJ Offline
                      JonB
                      wrote on last edited by
                      #10

                      @dan1973 You don't, or try Google translate!

                      1 Reply Last reply
                      0
                      • M Offline
                        M Offline
                        Mourad2021
                        wrote on last edited by
                        #11

                        Bonjour à tous,
                        J’ai changé la structure de mes classes, pour faire simple j’ai mis tout ce qui concerne les sockets dans un header sous forme de fonctions libres, du coté serveur je n’ai rien changé pour l’instatant.

                        Fichier header.h : ce fichier contient les inclusions communes et quelques define
                        #ifndef HEADER_H
                        #define HEADER_H
                        
                        // On inclut les fichiers standards
                        #include <iostream>
                        #include <stdlib.h>
                        #include <stdio.h>
                        #include <pthread.h>
                        #include <thread>
                        #include <mutex>
                        
                        //Les Fichiers Qt
                        #include <QPlainTextEdit>
                        #include <QPushButton>
                        
                        #define PORT 10000
                        
                        #if defined (WIN32) //Si nous sommes sous WINDOWS
                              #include <winsock2.h>
                              #include <windows.h>
                              //On peut remarquer que le type socklen_t qui existe sous Linux, n'est pas défini sous Windows. Ce type sert à stocker la taille d'une structures de type sockaddr_in. Ça n'est rien d'autre qu'un entier mais il nous évitera des problèmes éventuels de compilation sous Linux par la suite. Il va donc falloir le définir nous même à l'aide du mot clef typedef comme il suit
                              typedef int socklen_t;
                        
                        #elif defined (linux) //Si nous sommes sous LINUX
                              #include <sys/types.h>
                              #include <sys/socket.h>
                              #include <netinet/in.h>
                              #include <arpa/inet.h>
                              #include <unistd.h>
                        
                              // Define, qui nous serviront par la suite
                              #define INVALID_SOCKET -1
                              #define SOCKET_ERROR -1
                              #define closesocket(s) close(s)
                        
                              // De même
                              typedef int SOCKET;
                              typedef struct sockaddr_in SOCKADDR_IN;
                              typedef struct sockaddr SOCKADDR;
                        #endif
                        
                        struct Shared
                        {
                              int data;
                              pthread_mutex_t mut;
                              pthread_cond_t synchro;
                        };
                        
                        struct ThreadData
                        {
                              QPlainTextEdit *strucPlainText;
                              QPushButton *strucBtnOn;
                              QPushButton *strucBtnOff;
                              struct Shared *psh;
                        };
                        
                        struct MsgData
                        {
                              char nom[256];
                              char message[256];
                        };
                        
                        #endif // HEADER_H
                        
                        

                        Maintenant voici les fichiers Du côté client

                        Fichier fctclient.h

                        #ifndef FCTCLIENT_H
                        #define FCTCLIENT_H
                        
                        
                        #include "../SocketGraphicServer/header.h"
                        #include <QDebug>
                        #include <QPlainTextEdit>
                        #include <QString>
                        #include <QMessageBox>
                        
                        
                        /* Socket et contexte d'adressage du client */
                        SOCKET csock;
                        SOCKADDR_IN csin;
                        socklen_t crecsize;
                        int sock_err;
                        
                        QPlainTextEdit *m_plainTextEdit ;
                        struct ThreadData m_threadDataClient;
                        bool m_graphic;
                        struct MsgData m_msgDataClient;
                        bool boolConnection;
                        
                        void Initialisation(struct ThreadData &myThreadData);
                        bool FctConnection();
                        void FctDeconnection();
                        void* FctReceiveMsg(void *arg);
                        
                        #endif // FCTCLIENT_H
                        
                        

                        Fichier fctclient.cpp

                        #include "fctclient.h"
                        
                        void Initialisation(struct ThreadData &myThreadData)
                        {
                              m_graphic = true;
                              m_threadDataClient = myThreadData;
                        
                        #if defined (WIN32)
                              WSADATA WSAData;
                              int erreur = WSAStartup(MAKEWORD(2,2), &WSAData);
                        #elif
                              int erreur = 0;
                        #endif
                        
                              if(!erreur)
                              {
                                    /* Création de la socket */
                                    csock = socket(AF_INET, SOCK_STREAM, 0);
                                    printf("La socket client est %d\n", csock);
                                    /* Configuration de la connexion */
                                    csin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //127.0.0.1"); "192.168.0.12"
                                    csin.sin_family = AF_INET;
                                    csin.sin_port = htons(PORT);
                              }
                        }
                        
                        bool FctConnection()
                        {
                        
                              m_threadDataClient.strucPlainText->appendPlainText(QString("je suis la connection"));
                              bool returnVal = false;
                        
                              //Si on n'arrive pas à se connecter.
                              if(connect(csock, (SOCKADDR *)&csin, sizeof(csin)) == SOCKET_ERROR)
                              {
                                    //printf("Connexion à %s sur le port %d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
                                    // Attente pendant laquelle le client se connecte
                                    if(!m_graphic)
                                          printf("Impossible de se connecter.");
                                    else
                                          m_threadDataClient.strucPlainText->appendPlainText(QString("Impossible de se connecter."));
                                    returnVal = false;
                              }
                              //Si on arrive à se connecter
                              else
                              {
                                    if(!m_graphic)
                                          printf("Connexion à %s sur le port %d\n", inet_ntoa(csin.sin_addr), htons(csin.sin_port));
                                    else
                                    {
                                          m_threadDataClient.strucPlainText->appendPlainText(QString("Connexion à %1 sur le port %2.").arg(inet_ntoa(csin.sin_addr)).arg(htons(csin.sin_port)));
                                    }
                        
                                    returnVal = true;
                                    boolConnection = true;
                              }
                        
                              return returnVal;
                        }
                        
                        void FctDeconnection()
                        {
                              /* On ferme la socket précédemment ouverte */
                              closesocket(csock);
                              //QMessageBox::information(nullptr, "csock", QString::number(csock));
                        
                        #if defined (WIN32)
                              WSACleanup();
                        #endif
                              boolConnection = false;
                              m_threadDataClient.strucPlainText->appendPlainText(QString("Déconnexion"));
                        }
                        
                        void* FctReceiveMsg(void *arg)
                        {
                              qDebug() << "j'attends un message avant le while" ;
                              //m_msgDataClient = (MsgData*)arg;
                              while(boolConnection)
                              {
                                    if(recv(csock, (char*)&m_msgDataClient, sizeof(m_msgDataClient), 0) != SOCKET_ERROR)
                                    {
                        
                                          std::string nom = m_msgDataClient.nom;
                                          std::string message = m_msgDataClient.message;
                                          qDebug() << QString::fromStdString(nom);
                                          qDebug() << QString::fromStdString(message);
                                          pthread_mutex_lock(&m_threadDataClient.psh->mut);
                                          pthread_cond_signal(&m_threadDataClient.psh->synchro);
                                          pthread_mutex_unlock(&m_threadDataClient.psh->mut);
                                    }
                              }
                        
                        }
                        
                        

                        Fichier mainwindowclient.h

                        #ifndef MAINWINDOWCLIENT_H
                        #define MAINWINDOWCLIENT_H
                        
                        #include <QApplication>
                        #include <QMainWindow>
                        //#include "threadFunctions.h"
                        #include "fctclient.h"
                        
                        QT_BEGIN_NAMESPACE
                        namespace Ui { class MainWindowClient; }
                        QT_END_NAMESPACE
                        
                        class MainWindowClient : public QMainWindow
                        {
                              Q_OBJECT
                        
                        public:
                              MainWindowClient(QWidget *parent = nullptr);
                              ~MainWindowClient();
                              void FctConnectionsObjets();
                              void FctRcvMsg();
                              void* FctWriteMsg();
                        
                        public slots:
                              void SlotRcvMsg();
                              void SlotSetMessage(MsgData&);
                              void SlotConnection();
                              void SlotDeconnexion();
                        
                        private:
                              Ui::MainWindowClient *ui;
                              //ClassClient myClassClient;
                              //On déclare les thread
                              //std::thread threadRcvMsg;
                              pthread_t threadRcvMsg;
                              pthread_t threadWriteMsg;
                              //Les structures
                              struct Shared m_shared;
                              struct ThreadData m_threadDataClient;
                        };
                        #endif // MAINWINDOWCLIENT_H
                        
                        

                        Le fichier mainwindowclient.cpp

                        #include "mainwindowclient.h"
                        #include "ui_mainwindowclient.h"
                        
                        MainWindowClient::MainWindowClient(QWidget *parent)
                              : QMainWindow(parent)
                              , ui(new Ui::MainWindowClient)
                        {
                              ui->setupUi(this);
                              qDebug() << "entrée du constructeur";
                              m_shared =
                              {
                                    .data = 0,
                                    .mut = PTHREAD_MUTEX_INITIALIZER,
                                    .synchro = PTHREAD_COND_INITIALIZER,
                              };
                        
                              m_threadDataClient =
                              {
                                    .strucPlainText = ui->plainTextEditRapport,
                                    .strucBtnOn = ui->btnConDecon,
                                    .strucBtnOff = ui->btnDeconnecter,
                                    .psh = &m_shared,
                              };
                        
                              //myClassClient = ClassClient(m_threadDataClient);
                              FctConnectionsObjets();
                        }
                        
                        MainWindowClient::~MainWindowClient()
                        {
                              delete ui;
                        }
                        
                        void MainWindowClient::FctConnectionsObjets()
                        {
                              QObject::connect(ui->btnConDecon, SIGNAL(clicked()), this, SLOT(SlotConnection()));
                              QObject::connect(ui->btnDeconnecter, SIGNAL(clicked()), this, SLOT(SlotDeconnexion()));
                              //QObject::connect(this, SIGNAL(m_signa1(MsgData&)), this, SLOT(SlotEtMessage(MsgData&)));
                        }
                        
                        void MainWindowClient::SlotConnection()
                        {
                              //myClassClient = ClassClient(m_threadDataClient);
                              if(FctConnection())
                              {
                                    ui->btnConDecon->setText("&Déconnecter");
                                    SlotRcvMsg();
                              }
                        
                        }
                        
                        void MainWindowClient::SlotRcvMsg()
                        {
                              int ret1 =  pthread_create(&threadRcvMsg, NULL, FctReceiveMsg, nullptr);
                             // int ret2 =  pthread_create(&threadWriteMsg, NULL, FctWriteMsg, nullptr);
                              int ret2 =  pthread_create(&threadWriteMsg, NULL, [](void *ptr){static_cast<MainWindowClient*>(ptr)->FctWriteMsg(); return (void*)nullptr;}, nullptr);
                        
                              //int ret =  pthread_create(&threadRcvMsg, NULL, ClassClient::FctReceiveMsg, nullptr);
                              //threadRcvMsg = std::thread((FctReceiveMsg));
                              if(ret1 != 0) {
                                    ui->plainTextEditRapport->appendPlainText("Erreur : erreur de création de pthread_create() de \"threadRcvMsg\".");
                              }
                              else
                              {
                                    ui->plainTextEditRapport->appendPlainText("Succés : Création de pthread \"threadRcvMsg\" réussie");
                              }
                        
                        
                              if(ret2 != 0) {
                                    ui->plainTextEditRapport->appendPlainText("Erreur : erreur de création de pthread_create() de \"threadWriteMsg\".");
                              }
                              else
                              {
                                    ui->plainTextEditRapport->appendPlainText("Succés : Création de pthread \"threadWriteMsg\" réussie");
                              }
                        }
                        
                        void MainWindowClient::SlotSetMessage(MsgData&)
                        {
                              ui->plainTextEditRapport->appendPlainText("je suis set message");
                        }
                        
                        void* MainWindowClient::FctWriteMsg()
                        {
                              pthread_mutex_lock(&m_threadDataClient.psh->mut);
                              pthread_cond_wait(&m_threadDataClient.psh->synchro, &m_threadDataClient.psh->mut);
                              ui->plainTextEditRapport->appendPlainText("je suis FctWriteMsg message");
                              pthread_mutex_unlock(&m_threadDataClient.psh->mut);
                        }
                        
                        void MainWindowClient::SlotDeconnexion()
                        {
                              //threadRcvMsg.detach();
                              ui->btnConDecon->setText("&Connecter");
                              //myClassClient.FctDeconnection();
                              FctDeconnection();
                        }
                        
                        
                        

                        Fichier main.cpp cote client

                        #include "mainwindowclient.h"
                        
                        #include <QApplication>
                        #include <QLocale>
                        #include <QTranslator>
                        
                        int main(int argc, char *argv[])
                        {
                              QApplication a(argc, argv);
                              QTranslator translator;
                              const QStringList uiLanguages = QLocale::system().uiLanguages();
                              for (const QString &locale : uiLanguages) {
                                    const QString baseName = "SocketGraphicClient_" + QLocale(locale).name();
                                    if (translator.load(":/i18n/" + baseName)) {
                                          a.installTranslator(&translator);
                                          break;
                                    }
                              }
                              MainWindowClient w;
                              w.show();
                              return a.exec();
                        } 
                        
                        

                        Et voici les erreurs maintenant. Il y en a 33 mais j’en ai mis que 3. Je ne comprends pas d’où vient cette erreur de redéfinition de variables

                        :-1: erreur : debug/main.o:D:\Fichiers_applications\C++\Projets_QtCreator\Test\Revis_gnrle\Travaux_pratiques\SocketGraphic\build-SocketGraphicRoot-Desktop_Qt_6_3_1_MinGW_64_bit-Debug\SocketGraphicClient/../../SocketGraphicRoot/SocketGraphicClient/fctclient.h:13: multiple definition of `csock'; debug/fctclient.o:D:\Fichiers_applications\C++\Projets_QtCreator\Test\Revis_gnrle\Travaux_pratiques\SocketGraphic\build-SocketGraphicRoot-Desktop_Qt_6_3_1_MinGW_64_bit-Debug\SocketGraphicClient/../../SocketGraphicRoot/SocketGraphicClient/fctclient.h:13: first defined here
                        
                        :-1: erreur : debug/main.o:D:\Fichiers_applications\C++\Projets_QtCreator\Test\Revis_gnrle\Travaux_pratiques\SocketGraphic\build-SocketGraphicRoot-Desktop_Qt_6_3_1_MinGW_64_bit-Debug\SocketGraphicClient/../../SocketGraphicRoot/SocketGraphicClient/fctclient.h:14: multiple definition of `csin'; debug/fctclient.o:D:\Fichiers_applications\C++\Projets_QtCreator\Test\Revis_gnrle\Travaux_pratiques\SocketGraphic\build-SocketGraphicRoot-Desktop_Qt_6_3_1_MinGW_64_bit-Debug\SocketGraphicClient/../../SocketGraphicRoot/SocketGraphicClient/fctclient.h:14: first defined here
                        
                        :-1: erreur : debug/main.o:D:\Fichiers_applications\C++\Projets_QtCreator\Test\Revis_gnrle\Travaux_pratiques\SocketGraphic\build-SocketGraphicRoot-Desktop_Qt_6_3_1_MinGW_64_bit-Debug\SocketGraphicClient/../../SocketGraphicRoot/SocketGraphicClient/fctclient.h:15: multiple definition of `crecsize'; debug/fctclient.o:D:\Fichiers_applications\C++\Projets_QtCreator\Test\Revis_gnrle\Travaux_pratiques\SocketGraphic\build-SocketGraphicRoot-Desktop_Qt_6_3_1_MinGW_64_bit-Debug\SocketGraphicClient/../../SocketGraphicRoot/SocketGraphicClient/fctclient.h:15: first defined here
                        
                        

                        Merci d’avance de votre aide

                        JonBJ 1 Reply Last reply
                        0
                        • M Mourad2021

                          Bonjour à tous,
                          J’ai changé la structure de mes classes, pour faire simple j’ai mis tout ce qui concerne les sockets dans un header sous forme de fonctions libres, du coté serveur je n’ai rien changé pour l’instatant.

                          Fichier header.h : ce fichier contient les inclusions communes et quelques define
                          #ifndef HEADER_H
                          #define HEADER_H
                          
                          // On inclut les fichiers standards
                          #include <iostream>
                          #include <stdlib.h>
                          #include <stdio.h>
                          #include <pthread.h>
                          #include <thread>
                          #include <mutex>
                          
                          //Les Fichiers Qt
                          #include <QPlainTextEdit>
                          #include <QPushButton>
                          
                          #define PORT 10000
                          
                          #if defined (WIN32) //Si nous sommes sous WINDOWS
                                #include <winsock2.h>
                                #include <windows.h>
                                //On peut remarquer que le type socklen_t qui existe sous Linux, n'est pas défini sous Windows. Ce type sert à stocker la taille d'une structures de type sockaddr_in. Ça n'est rien d'autre qu'un entier mais il nous évitera des problèmes éventuels de compilation sous Linux par la suite. Il va donc falloir le définir nous même à l'aide du mot clef typedef comme il suit
                                typedef int socklen_t;
                          
                          #elif defined (linux) //Si nous sommes sous LINUX
                                #include <sys/types.h>
                                #include <sys/socket.h>
                                #include <netinet/in.h>
                                #include <arpa/inet.h>
                                #include <unistd.h>
                          
                                // Define, qui nous serviront par la suite
                                #define INVALID_SOCKET -1
                                #define SOCKET_ERROR -1
                                #define closesocket(s) close(s)
                          
                                // De même
                                typedef int SOCKET;
                                typedef struct sockaddr_in SOCKADDR_IN;
                                typedef struct sockaddr SOCKADDR;
                          #endif
                          
                          struct Shared
                          {
                                int data;
                                pthread_mutex_t mut;
                                pthread_cond_t synchro;
                          };
                          
                          struct ThreadData
                          {
                                QPlainTextEdit *strucPlainText;
                                QPushButton *strucBtnOn;
                                QPushButton *strucBtnOff;
                                struct Shared *psh;
                          };
                          
                          struct MsgData
                          {
                                char nom[256];
                                char message[256];
                          };
                          
                          #endif // HEADER_H
                          
                          

                          Maintenant voici les fichiers Du côté client

                          Fichier fctclient.h

                          #ifndef FCTCLIENT_H
                          #define FCTCLIENT_H
                          
                          
                          #include "../SocketGraphicServer/header.h"
                          #include <QDebug>
                          #include <QPlainTextEdit>
                          #include <QString>
                          #include <QMessageBox>
                          
                          
                          /* Socket et contexte d'adressage du client */
                          SOCKET csock;
                          SOCKADDR_IN csin;
                          socklen_t crecsize;
                          int sock_err;
                          
                          QPlainTextEdit *m_plainTextEdit ;
                          struct ThreadData m_threadDataClient;
                          bool m_graphic;
                          struct MsgData m_msgDataClient;
                          bool boolConnection;
                          
                          void Initialisation(struct ThreadData &myThreadData);
                          bool FctConnection();
                          void FctDeconnection();
                          void* FctReceiveMsg(void *arg);
                          
                          #endif // FCTCLIENT_H
                          
                          

                          Fichier fctclient.cpp

                          #include "fctclient.h"
                          
                          void Initialisation(struct ThreadData &myThreadData)
                          {
                                m_graphic = true;
                                m_threadDataClient = myThreadData;
                          
                          #if defined (WIN32)
                                WSADATA WSAData;
                                int erreur = WSAStartup(MAKEWORD(2,2), &WSAData);
                          #elif
                                int erreur = 0;
                          #endif
                          
                                if(!erreur)
                                {
                                      /* Création de la socket */
                                      csock = socket(AF_INET, SOCK_STREAM, 0);
                                      printf("La socket client est %d\n", csock);
                                      /* Configuration de la connexion */
                                      csin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //127.0.0.1"); "192.168.0.12"
                                      csin.sin_family = AF_INET;
                                      csin.sin_port = htons(PORT);
                                }
                          }
                          
                          bool FctConnection()
                          {
                          
                                m_threadDataClient.strucPlainText->appendPlainText(QString("je suis la connection"));
                                bool returnVal = false;
                          
                                //Si on n'arrive pas à se connecter.
                                if(connect(csock, (SOCKADDR *)&csin, sizeof(csin)) == SOCKET_ERROR)
                                {
                                      //printf("Connexion à %s sur le port %d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
                                      // Attente pendant laquelle le client se connecte
                                      if(!m_graphic)
                                            printf("Impossible de se connecter.");
                                      else
                                            m_threadDataClient.strucPlainText->appendPlainText(QString("Impossible de se connecter."));
                                      returnVal = false;
                                }
                                //Si on arrive à se connecter
                                else
                                {
                                      if(!m_graphic)
                                            printf("Connexion à %s sur le port %d\n", inet_ntoa(csin.sin_addr), htons(csin.sin_port));
                                      else
                                      {
                                            m_threadDataClient.strucPlainText->appendPlainText(QString("Connexion à %1 sur le port %2.").arg(inet_ntoa(csin.sin_addr)).arg(htons(csin.sin_port)));
                                      }
                          
                                      returnVal = true;
                                      boolConnection = true;
                                }
                          
                                return returnVal;
                          }
                          
                          void FctDeconnection()
                          {
                                /* On ferme la socket précédemment ouverte */
                                closesocket(csock);
                                //QMessageBox::information(nullptr, "csock", QString::number(csock));
                          
                          #if defined (WIN32)
                                WSACleanup();
                          #endif
                                boolConnection = false;
                                m_threadDataClient.strucPlainText->appendPlainText(QString("Déconnexion"));
                          }
                          
                          void* FctReceiveMsg(void *arg)
                          {
                                qDebug() << "j'attends un message avant le while" ;
                                //m_msgDataClient = (MsgData*)arg;
                                while(boolConnection)
                                {
                                      if(recv(csock, (char*)&m_msgDataClient, sizeof(m_msgDataClient), 0) != SOCKET_ERROR)
                                      {
                          
                                            std::string nom = m_msgDataClient.nom;
                                            std::string message = m_msgDataClient.message;
                                            qDebug() << QString::fromStdString(nom);
                                            qDebug() << QString::fromStdString(message);
                                            pthread_mutex_lock(&m_threadDataClient.psh->mut);
                                            pthread_cond_signal(&m_threadDataClient.psh->synchro);
                                            pthread_mutex_unlock(&m_threadDataClient.psh->mut);
                                      }
                                }
                          
                          }
                          
                          

                          Fichier mainwindowclient.h

                          #ifndef MAINWINDOWCLIENT_H
                          #define MAINWINDOWCLIENT_H
                          
                          #include <QApplication>
                          #include <QMainWindow>
                          //#include "threadFunctions.h"
                          #include "fctclient.h"
                          
                          QT_BEGIN_NAMESPACE
                          namespace Ui { class MainWindowClient; }
                          QT_END_NAMESPACE
                          
                          class MainWindowClient : public QMainWindow
                          {
                                Q_OBJECT
                          
                          public:
                                MainWindowClient(QWidget *parent = nullptr);
                                ~MainWindowClient();
                                void FctConnectionsObjets();
                                void FctRcvMsg();
                                void* FctWriteMsg();
                          
                          public slots:
                                void SlotRcvMsg();
                                void SlotSetMessage(MsgData&);
                                void SlotConnection();
                                void SlotDeconnexion();
                          
                          private:
                                Ui::MainWindowClient *ui;
                                //ClassClient myClassClient;
                                //On déclare les thread
                                //std::thread threadRcvMsg;
                                pthread_t threadRcvMsg;
                                pthread_t threadWriteMsg;
                                //Les structures
                                struct Shared m_shared;
                                struct ThreadData m_threadDataClient;
                          };
                          #endif // MAINWINDOWCLIENT_H
                          
                          

                          Le fichier mainwindowclient.cpp

                          #include "mainwindowclient.h"
                          #include "ui_mainwindowclient.h"
                          
                          MainWindowClient::MainWindowClient(QWidget *parent)
                                : QMainWindow(parent)
                                , ui(new Ui::MainWindowClient)
                          {
                                ui->setupUi(this);
                                qDebug() << "entrée du constructeur";
                                m_shared =
                                {
                                      .data = 0,
                                      .mut = PTHREAD_MUTEX_INITIALIZER,
                                      .synchro = PTHREAD_COND_INITIALIZER,
                                };
                          
                                m_threadDataClient =
                                {
                                      .strucPlainText = ui->plainTextEditRapport,
                                      .strucBtnOn = ui->btnConDecon,
                                      .strucBtnOff = ui->btnDeconnecter,
                                      .psh = &m_shared,
                                };
                          
                                //myClassClient = ClassClient(m_threadDataClient);
                                FctConnectionsObjets();
                          }
                          
                          MainWindowClient::~MainWindowClient()
                          {
                                delete ui;
                          }
                          
                          void MainWindowClient::FctConnectionsObjets()
                          {
                                QObject::connect(ui->btnConDecon, SIGNAL(clicked()), this, SLOT(SlotConnection()));
                                QObject::connect(ui->btnDeconnecter, SIGNAL(clicked()), this, SLOT(SlotDeconnexion()));
                                //QObject::connect(this, SIGNAL(m_signa1(MsgData&)), this, SLOT(SlotEtMessage(MsgData&)));
                          }
                          
                          void MainWindowClient::SlotConnection()
                          {
                                //myClassClient = ClassClient(m_threadDataClient);
                                if(FctConnection())
                                {
                                      ui->btnConDecon->setText("&Déconnecter");
                                      SlotRcvMsg();
                                }
                          
                          }
                          
                          void MainWindowClient::SlotRcvMsg()
                          {
                                int ret1 =  pthread_create(&threadRcvMsg, NULL, FctReceiveMsg, nullptr);
                               // int ret2 =  pthread_create(&threadWriteMsg, NULL, FctWriteMsg, nullptr);
                                int ret2 =  pthread_create(&threadWriteMsg, NULL, [](void *ptr){static_cast<MainWindowClient*>(ptr)->FctWriteMsg(); return (void*)nullptr;}, nullptr);
                          
                                //int ret =  pthread_create(&threadRcvMsg, NULL, ClassClient::FctReceiveMsg, nullptr);
                                //threadRcvMsg = std::thread((FctReceiveMsg));
                                if(ret1 != 0) {
                                      ui->plainTextEditRapport->appendPlainText("Erreur : erreur de création de pthread_create() de \"threadRcvMsg\".");
                                }
                                else
                                {
                                      ui->plainTextEditRapport->appendPlainText("Succés : Création de pthread \"threadRcvMsg\" réussie");
                                }
                          
                          
                                if(ret2 != 0) {
                                      ui->plainTextEditRapport->appendPlainText("Erreur : erreur de création de pthread_create() de \"threadWriteMsg\".");
                                }
                                else
                                {
                                      ui->plainTextEditRapport->appendPlainText("Succés : Création de pthread \"threadWriteMsg\" réussie");
                                }
                          }
                          
                          void MainWindowClient::SlotSetMessage(MsgData&)
                          {
                                ui->plainTextEditRapport->appendPlainText("je suis set message");
                          }
                          
                          void* MainWindowClient::FctWriteMsg()
                          {
                                pthread_mutex_lock(&m_threadDataClient.psh->mut);
                                pthread_cond_wait(&m_threadDataClient.psh->synchro, &m_threadDataClient.psh->mut);
                                ui->plainTextEditRapport->appendPlainText("je suis FctWriteMsg message");
                                pthread_mutex_unlock(&m_threadDataClient.psh->mut);
                          }
                          
                          void MainWindowClient::SlotDeconnexion()
                          {
                                //threadRcvMsg.detach();
                                ui->btnConDecon->setText("&Connecter");
                                //myClassClient.FctDeconnection();
                                FctDeconnection();
                          }
                          
                          
                          

                          Fichier main.cpp cote client

                          #include "mainwindowclient.h"
                          
                          #include <QApplication>
                          #include <QLocale>
                          #include <QTranslator>
                          
                          int main(int argc, char *argv[])
                          {
                                QApplication a(argc, argv);
                                QTranslator translator;
                                const QStringList uiLanguages = QLocale::system().uiLanguages();
                                for (const QString &locale : uiLanguages) {
                                      const QString baseName = "SocketGraphicClient_" + QLocale(locale).name();
                                      if (translator.load(":/i18n/" + baseName)) {
                                            a.installTranslator(&translator);
                                            break;
                                      }
                                }
                                MainWindowClient w;
                                w.show();
                                return a.exec();
                          } 
                          
                          

                          Et voici les erreurs maintenant. Il y en a 33 mais j’en ai mis que 3. Je ne comprends pas d’où vient cette erreur de redéfinition de variables

                          :-1: erreur : debug/main.o:D:\Fichiers_applications\C++\Projets_QtCreator\Test\Revis_gnrle\Travaux_pratiques\SocketGraphic\build-SocketGraphicRoot-Desktop_Qt_6_3_1_MinGW_64_bit-Debug\SocketGraphicClient/../../SocketGraphicRoot/SocketGraphicClient/fctclient.h:13: multiple definition of `csock'; debug/fctclient.o:D:\Fichiers_applications\C++\Projets_QtCreator\Test\Revis_gnrle\Travaux_pratiques\SocketGraphic\build-SocketGraphicRoot-Desktop_Qt_6_3_1_MinGW_64_bit-Debug\SocketGraphicClient/../../SocketGraphicRoot/SocketGraphicClient/fctclient.h:13: first defined here
                          
                          :-1: erreur : debug/main.o:D:\Fichiers_applications\C++\Projets_QtCreator\Test\Revis_gnrle\Travaux_pratiques\SocketGraphic\build-SocketGraphicRoot-Desktop_Qt_6_3_1_MinGW_64_bit-Debug\SocketGraphicClient/../../SocketGraphicRoot/SocketGraphicClient/fctclient.h:14: multiple definition of `csin'; debug/fctclient.o:D:\Fichiers_applications\C++\Projets_QtCreator\Test\Revis_gnrle\Travaux_pratiques\SocketGraphic\build-SocketGraphicRoot-Desktop_Qt_6_3_1_MinGW_64_bit-Debug\SocketGraphicClient/../../SocketGraphicRoot/SocketGraphicClient/fctclient.h:14: first defined here
                          
                          :-1: erreur : debug/main.o:D:\Fichiers_applications\C++\Projets_QtCreator\Test\Revis_gnrle\Travaux_pratiques\SocketGraphic\build-SocketGraphicRoot-Desktop_Qt_6_3_1_MinGW_64_bit-Debug\SocketGraphicClient/../../SocketGraphicRoot/SocketGraphicClient/fctclient.h:15: multiple definition of `crecsize'; debug/fctclient.o:D:\Fichiers_applications\C++\Projets_QtCreator\Test\Revis_gnrle\Travaux_pratiques\SocketGraphic\build-SocketGraphicRoot-Desktop_Qt_6_3_1_MinGW_64_bit-Debug\SocketGraphicClient/../../SocketGraphicRoot/SocketGraphicClient/fctclient.h:15: first defined here
                          
                          

                          Merci d’avance de votre aide

                          JonBJ Offline
                          JonBJ Offline
                          JonB
                          wrote on last edited by JonB
                          #12

                          @Mourad2021 said in Problème avec pthread et QPlainTextEdit:

                          fctclient.h

                          Cette fctclient.h ne peur peut pas avoir #include "fctclient.h" plus qu'une seule fois dans un fichier .cpp. Vous l'avez dans fctclient.cpp et dans mainwindowclient.h -> main.cpp.

                          M 1 Reply Last reply
                          2
                          • SGaistS Offline
                            SGaistS Offline
                            SGaist
                            Lifetime Qt Champion
                            wrote on last edited by
                            #13

                            Pourquoi avoir créé des variables statiques pour tous ces éléments ?

                            Interested in AI ? www.idiap.ch
                            Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                            1 Reply Last reply
                            0
                            • JonBJ JonB

                              @Mourad2021 said in Problème avec pthread et QPlainTextEdit:

                              fctclient.h

                              Cette fctclient.h ne peur peut pas avoir #include "fctclient.h" plus qu'une seule fois dans un fichier .cpp. Vous l'avez dans fctclient.cpp et dans mainwindowclient.h -> main.cpp.

                              M Offline
                              M Offline
                              mpergand
                              wrote on last edited by mpergand
                              #14

                              @JonB said in Problème avec pthread et QPlainTextEdit:

                              Cette fctclient.h ne peur pas avoir

                              Scary words :)

                              Comme l'a noté @JonB , le fichier est inclus plusieurs fois et comme :

                              /* Socket et contexte d'adressage du client */
                              SOCKET csock;
                              SOCKADDR_IN csin;
                              socklen_t crecsize;
                              int sock_err;

                              sont déclarées dans le .h, elles sont ainsi définies plusieurs fois.

                              1 Reply Last reply
                              1
                              • M Offline
                                M Offline
                                Mourad2021
                                wrote on last edited by
                                #15

                                Merci à tous de me répondre, ça m'aide beaucoup pour ne pas perdre du temps.
                                JonB en fait je l'utilise mainwindowclient dont :

                                #include "fctclient.h" dans mainwindowclient.h
                                
                                

                                et dans fctclient.cpp ce qui est normal pour définir les fonctions

                                par contre

                                mpergand ça marche le fait de déplacer la déclaration des variables dans le fctclient.cpp

                                SGaist : elles ne sont pas déclarées statiques.
                                en tout cas merci à tous pour votre aide.
                                je vous tiendrai au courant de la suite.

                                M 1 Reply Last reply
                                0
                                • M Mourad2021

                                  Merci à tous de me répondre, ça m'aide beaucoup pour ne pas perdre du temps.
                                  JonB en fait je l'utilise mainwindowclient dont :

                                  #include "fctclient.h" dans mainwindowclient.h
                                  
                                  

                                  et dans fctclient.cpp ce qui est normal pour définir les fonctions

                                  par contre

                                  mpergand ça marche le fait de déplacer la déclaration des variables dans le fctclient.cpp

                                  SGaist : elles ne sont pas déclarées statiques.
                                  en tout cas merci à tous pour votre aide.
                                  je vous tiendrai au courant de la suite.

                                  M Offline
                                  M Offline
                                  mpergand
                                  wrote on last edited by
                                  #16

                                  @Mourad2021 said in Problème avec pthread et QPlainTextEdit:

                                  ça marche le fait de déplacer la déclaration des variables dans le fctclient.cpp

                                  Il existe en C un mot magique: extern

                                  1 Reply Last reply
                                  0

                                  • Login

                                  • Login or register to search.
                                  • First post
                                    Last post
                                  0
                                  • Categories
                                  • Recent
                                  • Tags
                                  • Popular
                                  • Users
                                  • Groups
                                  • Search
                                  • Get Qt Extensions
                                  • Unsolved