Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

  1. #1
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    avril 2017
    Messages
    48
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 21
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : avril 2017
    Messages : 48
    Points : 23
    Points
    23

    Par défaut Serveur multithread à partir d'un serveur basique

    Bonjour à tous,

    J'ai réaliser un serveur qui enregistre ce que lui envoi le client puis écoute le port suivant. Je m'explique, j'ai 24 cartes en mode client possédant toute un module ethernet qui envoi leur données sur un port (entre 50001 et 50024). Le serveur écoute le port 50001 puis accepte la connexion, enregistre les données et enfin passe au port 50002 ... Jusqu'au port 50024 puis il revient au port 50001. Le processus est beaucoup trop long et j'aimerai utiliser le multithreading. Malheureusement, je n'y arrive pas.
    Voici mon code de base :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
     
    #pragma hdrstop
    #include <condefs.h>
     
    //---------------------------------------------------------------------------
    #pragma argsused
    #include <winsock2.h>                         // Librairie servant aux sockets
    #pragma comment(lib, "ws2_32.lib")
    #include <stdlib.h>
    #include <stdio.h>
    #include <fstream>
    #include <iostream>
    #include <string>
     
    using namespace std;
     
    int main()
    {
        FreeConsole();                                            // Permet de cacher la console pendant l'execution du programme
        SOCKET val;                                               // Prend la valeur du retour du accept()
        char buff[70];                                            // Tableau où l'on va enregistrer ce qu'on reçoit
        int num_sondes_micro;                                     // Variable où l'on va enregistrer la correspondance entre les lettres et les sondes(voir abcd[][] dans pilotes.cpp)
                                                                  // Exemple : A => 0, B => 1 , ...
        int tab_lue[12*12*10] = {0};                                    // Tableau où on enregistre les valeurs des sondes
       // int tab_lue[10] = {0};
        int valeur_sonde;                                         // Où l'on met la valeur de la sonde que l'on vient de lire
        string valeur_sonde_str;
        int compt = 0;
        int p;
        string lignetxt, contenu;
        int j = 0;
        int numero_port_micro = 50001;
        int var_pont = 0;                                         // Variable que l'on va ajouter à num_sonde_micro pour chaque changement de pont (pour positionner les valeurs dans le tableau)
     
        while(1)
        {
     
        WSADATA WSAData;                                          // Utilisée pour le démarrage de WSAStartup()
        WSAStartup(MAKEWORD(2,0), &WSAData);                      // Pour prévenir l'ordinateur que nous allon utiliser des sockets
     
     
        SOCKET sock;                                              // Variable pour définir le socket
        SOCKADDR_IN sin;                                          // La struct du SOCKADDR contient les informations techniques du socket
        sin.sin_addr.s_addr = htonl(INADDR_ANY);                  // Définie l'adresse serveur, si on code pour un client, sin.sin_addr.s_addr = inet_addr("127.0.0.1");
        sin.sin_family		= AF_INET;                    // Définie le type de socket, AF_INET pour internet
        sin.sin_port		= htons(numero_port_micro);   // Définie le port où le serveur est en écoute
        sock = socket(AF_INET,SOCK_STREAM,0);                     // Création du socket
        bind(sock, (SOCKADDR *)&sin, sizeof(sin));                // Attache le socket au port et à l'adresse définie plus haut
     
        listen(sock, SOMAXCONN);                                  // On écoute le port sur le socket
     
            int sizeof_sin = sizeof(sin);                         // calcule la taille de sin
            val = accept(sock, (SOCKADDR *)&sin, &sizeof_sin);    // Permet d'accepter la connexion
            if(val != INVALID_SOCKET)                             // Si on nous retourne autre chose que INVALID_SOCKET
            {
                    // Fonctions à éxécuter sur le socket.
                   recv(val, buff, sizeof(buff), 0);              // On reçoit les valeurs du module EZL et on les place dans buff
     
     
                    ofstream fichier("test_micro.txt", ios::out | ios::binary);  // ouverture en écriture avec effacement du fichier ouvert
     
            if(fichier)                            // Si le fichier s'ouvre
            {
                    for(int i = 0; i<70; i++){     // pour i allant de 0 à 70,
                           if((buff[i] == ';')||(buff[i] == ' ')||(buff[i] == '0')||(buff[i] == '1')||(buff[i] == '2')||(buff[i] == '3')||(buff[i] == '4')||(buff[i] == '5')||(buff[i] == '6')||(buff[i] == '7')||(buff[i] == '8')||(buff[i] == '9')||(buff[i] == 'A')||(buff[i] == 'B')||(buff[i] == 'C')||(buff[i] == 'D')||(buff[i] == 'E')||(buff[i] == 'F')||(buff[i] == 'G')||(buff[i] == 'H')||(buff[i] == 'I')||(buff[i] == 'J')){
                                   fichier << buff[i];                     // On enregistre le caractère lu dans le fichier texte
                           }
     
                    }   //fin for
                    fichier.close();
           }     // fin if(fichier)
           else{
                    cerr << "Impossible d'ouvrir le fichier !" << endl;
                    return 0;
           }   // fin else
     
     
     
    //***********à cette étape, nous avons enregistrer les caractères dans le fichier txt**************//
    /**Maintenant, il faut le parcourir pour faire correspondre les lettres et les valeurs aux sondes**/
     
             ifstream fichier2("test_micro.txt", ios::in);                               // on ouvre en lecture
             if(fichier2){                                                               // si l'ouverture a fonctionnée
     
                    while (!fichier2.eof()){                                             // eof est le flag de fin de fichier il se met a 1 quand on a atteint la fin du fichier.
                     getline(fichier2,lignetxt);                                         // On recupere une ligne du fichier sous la forme d'un string
                      for(j; j < 70/*lignetxt.length()*/; j++) {                         // ligne[j] renvoie le caractère placer a la j ème position; allant jusqu'à 80 pour avoir les 10 valeurs
     
                            switch(lignetxt[j]){                                         // On fait la correspondance entre les lettres et les sondes (voir abcd[][] colonne n dans pilotes.cpp)
                                    case 'A':                        // S1
                                            num_sondes_micro = 0;
                                            compt++;
                                            break;
                                    case 'B':                        // S2
                                            num_sondes_micro = 1;
                                            compt++;
                                            break;
                                    case 'C':                        // S3
                                            num_sondes_micro = 2;
                                            compt++;
                                            break;
                                    case 'D':                        // S4
                                            num_sondes_micro = 4;
                                            compt++;
                                            break;
                                    case 'E':                        // S5
                                            num_sondes_micro = 5;
                                            compt++;
                                            break;
                                    case 'F':                        // S6
                                            num_sondes_micro = 6;
                                            compt++;
                                            break;
                                    case 'G':                        // HG
                                            num_sondes_micro = 3;
                                            compt++;
                                            break;
                                    case 'H':                        // HD
                                            num_sondes_micro = 7;
                                            compt++;
                                            break;
                                    case 'I':                        // TG
                                            num_sondes_micro = 8;
                                            compt++;
                                            break;
                                    case 'J':                        // TD
                                            num_sondes_micro = 9;
                                            compt++;
                                            break;
                                    /*case ' ':
                                            buff[i] = '0';
                                            break; */
                                    defaut:
     
                            }   //fin switch
     
                      if(compt == 1){
                            p = j + 1;
                            valeur_sonde_str = lignetxt.substr(p,9);
                            valeur_sonde = atoi(valeur_sonde_str.c_str());           // Conversion string -> int
                            compt = 0;
                            j += 6;
                            tab_lue[num_sondes_micro + var_pont] = valeur_sonde;         // On enregistre la valeur de la sonde dans tab_lue suivant la sonde
                      }
     
     
                      }   //fin for
                    }   // fin while
     
                    fichier2.close();
                    j = 0;
                    numero_port_micro++;
                    var_pont += 10;                 // On incrémente de 10 car il y a 10 valeurs à placer dans le tableau
                    if(var_pont >= 239){              // Si on est au pont n°24, on repasse au 1
                         var_pont = 0;
                    }
     
             }    // fin if(fichier2)
             else{
                    cerr << "Impossible d'ouvrir le fichier !" << endl;
                    return 0;
             }   // fin else
        }  // fin if(val != INVALID_SOCKET)
     
     
     
        closesocket(sock);      // Ferme le socket sock
        closesocket(val);       // Ferme le socket val
        WSACleanup();           // Met fin à l'utilisation de la DLL Winsock 2
       // return 0;
     }    // fin while
    } // fin main()
    Je suis sous C++ builder 4

    Merci !

  2. #2
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Ingénieur systèmes embarqués
    Inscrit en
    juin 2009
    Messages
    3 934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Ingénieur systèmes embarqués

    Informations forums :
    Inscription : juin 2009
    Messages : 3 934
    Points : 10 874
    Points
    10 874
    Billets dans le blog
    1

    Par défaut

    Bonjour,

    Un vilain mélange de C et de C++ que tu nous fais là Est-ce voulu ? Si tu fais du C++, et non du C, on ne te proposera pas les mêmes solutions. Après, il n'y a pas de miracle, un code penser pour faire du mono-thread doit être en partie repenser pour faire du multithread. Une solution très simple pourrait être de passer le numéro du port en paramètre du programme et lancer le programme 24 fois. Si ce n'est pas possible ou pas adapté, il faut tu crées une fonction qui fait le taf pour un port et demande à 24 threads de l'exécuter. Mais pour faire des threads, on en revient à la question : C ou C++ ?

  3. #3
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    avril 2017
    Messages
    48
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 21
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : avril 2017
    Messages : 48
    Points : 23
    Points
    23

    Par défaut

    Merci de ta réponse !
    Tout d'abord, il faut savoir que je n'avais jamais fait de "communication réseau" type client serveur. J'ai donc fait avec les cours que j'ai trouvé. Mais ce programme va venir ce greffer sur un autre beaucoup plus conséquent en C++ (malgré qu'il y ai aussi quelques parties en C).
    C ou C++, je préférerais C++ mais si ça marche en C, pas de problème
    Ne pas oublié que je suis sous C++ Builder 4

    Placer le port en paramètre n'est pas possible pour mon cas ...

    J'ai déjà fais un thread une fois pour exécuter un délais sans bloquer le programme principal mais c'est tout. Je ne vois pas trop comment faire à part créer 24 thread avec 24 fichier .cpp mais d'après ce que j'ai vu, c'est plus "simple" que ça.
    Aurais-tu un bon tuto qui pourrait me servir ?

  4. #4
    Rédacteur/Modérateur

    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    5 476
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 5 476
    Points : 23 793
    Points
    23 793

    Par défaut

    Un serveur qui écoute sur 24 ports différents mais 1 seul à la fois ?! C'est pas commun
    Quel processus est long ?
    Tu comptes multi-threader quoi ? Les 24 ports ? Les traitements après réception sur chaque port ?

    Ton code actuel est déjà borderline.
    Pourquoi réinitialiser winsock à chaque fois ?!
    Tu ne vérifies aucun code d'erreur.
    La réception marche par chance vu que tu lis tout en une fois.
    A quoi sert d'enregistrer dans un fichier si c'est juste pour le relire directement ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  5. #5
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    avril 2017
    Messages
    48
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 21
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : avril 2017
    Messages : 48
    Points : 23
    Points
    23

    Par défaut

    Mon serveur écoute pour le moment 24 ports mais je veux utiliser le multithread pour qu'il n'écoute qu'un seul port mais aussi 24 client à la fois puisque écouter 24 ports l'un après l'autre est trop long.
    Mon client est un module ethernet EZL 50l. Un pic lui envoi des valeurs d'après un programme que j'ai fais.
    J'enregistre dans un fichier les valeurs que me donne mon client puis je passe au suivant.
    Je les traites dans un autre programme

  6. #6
    Rédacteur/Modérateur

    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    5 476
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 5 476
    Points : 23 793
    Points
    23 793

    Par défaut

    Tu n'as bien heureusement pas besoin d'écouter sur 24 ports pour avoir 24 clients... Sinon on serait pas dans la merde!
    Select, poll et mode non bloquant sont faits pour ça.

    Si c'est un autre programme qui traite le fichier alors que fait le code de lecture et traitement ici ?
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  7. #7
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    avril 2017
    Messages
    48
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 21
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : avril 2017
    Messages : 48
    Points : 23
    Points
    23

    Par défaut

    J'en ai besoin pour pouvoir identifier mon client et mes valeurs.
    C'est un test pour voir si les valeurs sont les bonnes.

  8. #8
    Rédacteur/Modérateur

    Homme Profil pro
    Network game programmer
    Inscrit en
    juin 2010
    Messages
    5 476
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 31
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : juin 2010
    Messages : 5 476
    Points : 23 793
    Points
    23 793

    Par défaut

    Ce test ne devrait dans tous les cas pas avoir à rouvrir et lire le fichier quand les données sont disponibles 3 lignes au-dessus directement en RAM..
    Quand on veut améliorer des performances, on cherche à corriger ces problèmes (simples) d'abord, pas par rajouter du multithreading.

    Quant à identifier un client, soit le client est fixe et connu et peut être reconnu depuis la connexion, soit il envoie son identifiant lors de la connexion pour s'annoncer et que le serveur sache que cette connexion correspond à ce client.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [Serveur]Multithreading obligatoire pour un serveur ?
    Par Artifice dans le forum Threads & Processus
    Réponses: 7
    Dernier message: 12/11/2010, 08h43
  2. Arrêt d'un serveur multithread
    Par bambou dans le forum IO
    Réponses: 7
    Dernier message: 07/07/2010, 17h04
  3. Backup d'un PC Client a partir d'un serveur
    Par Sendo dans le forum Applications et environnements graphiques
    Réponses: 1
    Dernier message: 22/05/2006, 18h41
  4. Réponses: 5
    Dernier message: 11/01/2006, 08h58

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo