Partage
  • Partager sur Facebook
  • Partager sur Twitter

Threads/Sokets

optimisation serveur client

    9 juin 2006 à 9:53:08

    Bonjour, je debute avec le C++, les sokets, les threads et je me retrouve avec pleins de variables globales dans le programme qui suit (y dois pas avoir que ca qui pourrais être amelioré) et les variables globales c'est pas térrible parait-il. J'acceppete toutes les critiques constructives (attention c long ^^) merci d'avance.

    // CODE DU SERVEUR
    #include <iostream>
    #include <string>   // pour std::string
    #include <winsock2.h>
    using namespace std;

    unsigned long WINAPI recep(void* params);
    unsigned long WINAPI envoi(void* params);

    SOCKET server;
    SOCKET sock;
    HANDLE h1;
    HANDLE h2;

    //message de bienvenu
    char bien[] = "Bienvenu sur mon serveur^^\0";
    char buffer[50]={0};
    char bufferRe[50]={0};
    string pseudoC;
    char pseudo[20] = "Serveur";
    int enteteR=0;
    int enteteE=0;

    void quitter();

    int main(int argc, char *argv[])
    {
        WSADATA wsa;
        WSAStartup(MAKEWORD(2,0),&wsa); // initialise l'utilisation de ws2_32.dll

        SOCKADDR_IN sinserv;
        SOCKADDR_IN sin;

        int port = 2000;
        //cin >> port;
        cout << "Port : " << port << endl;
        //cin >> pseudo;
        cout << "Pseudo : " << pseudo << endl;
        cout << "----------------\n";

        sinserv.sin_family=AF_INET;
        sinserv.sin_addr.s_addr=INADDR_ANY; // accepte toutes les IP
        sinserv.sin_port=htons(port);       // port du serveur
        server=socket(AF_INET,SOCK_STREAM,0); // crée le socket.
        bind(server,(SOCKADDR*)&sinserv,sizeof(sinserv)); // fournit une adresse locale au socket

        listen(server,0); // écouter le port donc met le socket en état d'attente d'une connexion extérieure
        int sinsize;

        while(1)
        {
            sinsize=sizeof(sin);
            // extrait la première connexion de la file d'attente et crée un nouveau socket
            if((sock=accept(server,(SOCKADDR*)&sin,&sinsize))!=INVALID_SOCKET)
            {
                // recupere l'IP du connecte + la converie en une chaîne de caractères + l'affiche
                cout << "Connexion acceptee: " << inet_ntoa(sin.sin_addr) << "\n";
                // reception
                h1=CreateThread(NULL,0,recep,NULL,0,0);
                // envoie
                h2=CreateThread(NULL,0,envoi,NULL,0,0);
            }
        }
        return 0;
    }

    // reçoit
    unsigned long WINAPI recep(void* params)
    {
            while(1)
            {
                memset(bufferRe,0,sizeof(bufferRe)); // initialise à 0 le tableau
                recv(sock,bufferRe,sizeof(bufferRe),0); // reçoit des données du socket
                if (enteteR <2) { // reception entete
                    if (enteteR<1)
                        cout << bufferRe; // message d'arrive
                    else
                        pseudoC = bufferRe;  // pseudo du client
                    enteteR++;
                }
                else if(!strcmp(bufferRe,"/quit\n") || !strcmp(bufferRe,"\0")) { // Le client ce deconnecte
                    cout << "Deconnexion du client\n"; // affiche message deconexion
                    quitter();
                }
                else
                    cout << pseudoC << "=> " << bufferRe; // affiche les messages
            Sleep(10);
            }
            return 0;
    }

    // envoie
    unsigned long WINAPI envoi(void* params)
    {
            while(1)
            {
                if (enteteE<2){ // envoie entete...
                if(enteteE<1)
                    send(sock,bien,sizeof(bien),0); // message bienvenu
                else
                    send(sock,pseudo,sizeof(pseudo),0); // Pseudo
                enteteE++;
                }
                else{
                memset(buffer,0,sizeof(buffer)); // initialise à 0 , http://ilay.org/yann/articles/mem/mem1.html
                fgets(buffer, 49, stdin); // saisie
                send(sock,buffer,sizeof(buffer),0); // envoie des données sur le socket
                }
            Sleep(10);
            }
            return 0;
    }

    void quitter()
    {
        memset(bufferRe,0,sizeof(bufferRe)); // initialise à 0 le tableau
        enteteR=0; // remise a zero pour avoir la possibilite de reafficher le message de bienvenu
        enteteE=0;
        pseudoC = "";
        TerminateThread(h1,0); // ferme les threads
        TerminateThread(h2,0);
    }



    // CODE DU CLIENT
    #include <iostream>
    #include <string>
    #include <winsock2.h>
    using namespace std;

    unsigned long WINAPI recep(void* params);
    unsigned long WINAPI envoi(void* params);

    SOCKET sock;
    SOCKADDR_IN sin;
    HANDLE h1;
    HANDLE h2;

    //message de bienvenu
    char bien[] = "Arriver de la brebis Doly ^^\n\0";
    char bufferC[50]={0};
    char bufferReC[50]={0};
    string pseudoS;
    char pseudo[20] = "Doly\0";
    bool ok = true;
    int enteteR=0;
    int enteteE=0;

    void quitter();

    int main(int argc, char *argv[])
    {
        WSADATA wsa;
        WSAStartup(MAKEWORD(2,0),&wsa); // initialise l'utilisation de ws2_32.dll

        char ip[15] = "127.0.0.1";
        int port = 2000;
        //cin >> ip;
        cout << "Ip : " << ip << endl;
        //cin >> port;
        cout << "Port : " << port << endl;
        //cin >> pseudo;
        cout << "Pseudo : " << pseudo << endl;
        cout << "----------------\n";

        sin.sin_family=AF_INET;
        sin.sin_addr.s_addr=inet_addr(ip);
        sin.sin_port=htons(port);
        sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); // crée le socket.
        bind(sock,(SOCKADDR*)&sin,sizeof(sin)); // fournit une adresse locale au socket

        if(connect(sock,(SOCKADDR*)&sin,sizeof(sin))) // établit la connexion avec un socket
        { //connect renvoie true en cas d'échec
            cout << "La connection a echoue";
            system("PAUSE");
            exit(0);
        }
        // recupere l'IP du connecte + la converie en une chaîne de caractères + l'affiche
        cout << "Connexion sur serveur: " << inet_ntoa(sin.sin_addr) << "\n";
        // envoie
        h1=CreateThread(NULL,0,envoi,NULL,0,0);
        // reception
        h2=CreateThread(NULL,0,recep,NULL,0,0);

        while(ok)   Sleep(1000);


        cout << "Connection fermer\n"; // message de deconnexion
        Sleep(2000);
        WSACleanup();// Les WSA se déchargent de cette façon. sa fait + propre ;) stoppe l'utilisation de ws2_32.dll
        return 0;
    }

    // reçoit
    unsigned long WINAPI recep(void* params)
    {
            while(ok)
            {
                memset(bufferReC,0,sizeof(bufferReC)); // initialise à 0
            recv(sock,bufferReC,sizeof(bufferReC),0); // reçoit des données du socket
            if (enteteR<2){ // reception entete ...
                if(enteteR<1)
                    cout << bufferReC << endl; // message arriver
                else
                    pseudoS = bufferReC; // // reçoit Pseudo
                enteteR++;
            }
            else if(!strcmp(bufferReC,"\0")) { // Deconnexion du serveur
                cout << "Deconnexion du serveur\n";
                quitter();
            }
            else
                cout << pseudoS << "=> " << bufferReC;
            Sleep(10);
            }
            return 0;
    }

    // envoie
    unsigned long WINAPI envoi(void* params)
    {
            while(ok)
            {
            if (enteteE<2){ // envoie entete...
                if(enteteE<1)
                    send(sock,bien,sizeof(bien),0); // message bienvenu
                else
                    send(sock,pseudo,sizeof(pseudo),0); // Pseudo
                enteteE++;
                }
            else{
                memset(bufferC,0,sizeof(bufferC)); // initialise à 0
                fgets(bufferC, 49, stdin); // saisie
                send(sock,bufferC,sizeof(bufferC),0); // envoie des données sur le socket
                if(!strcmp(bufferC,"/quit\n"))
                    quitter();
            }
            Sleep(10);
            }
            return 0;
    }

    void quitter()
    {
        memset(bufferReC,0,sizeof(bufferReC)); // initialise à 0 le tableau
        enteteR=0; // remise a zero pour avoir la possibilite de reafficher le message de bienvenu
        enteteE=0;
        pseudoS = "";
        ok = false;
        TerminateThread(h1,0);
        TerminateThread(h2,0);
    }

    • Partager sur Facebook
    • Partager sur Twitter
      9 juin 2006 à 13:49:08

      Ouai c'est bien.
      Pour eviter les variable global tu peux passe le pointeur d'une class ou d'une structure au thread par les arguments.

      exemple:



      thread_Reception(void *NombObjet)
      {
      C_TypeDeLobjet * NombObjet = reinterpret_cast<C_TypeDeLobjet*>(NombObjet);// remettre l'objet avec le type de départ en l'occurence ici c'est C_TypeDeLobjet


      ...

      }


      Bonne continuation
      • Partager sur Facebook
      • Partager sur Twitter
        10 juin 2006 à 5:02:32

        Merci Toun1, j'ais bien essaye mais ... :euh: apparement je ne maitrise pas encore assez bien les classes.
        • Partager sur Facebook
        • Partager sur Twitter

        Threads/Sokets

        × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
        × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
        • Editeur
        • Markdown