IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
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

Réseau C Discussion :

Threads : problème d'exécution parallèle


Sujet :

Réseau C

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 6
    Points : 5
    Points
    5
    Par défaut Threads : problème d'exécution parallèle
    Bonsoir à tous,
    Voilà donc j'ai un projet dont la base est de créer une sorte de "chat", le problème est le suivant (par étapes) :
    - Je commence par créer une application serveur et une application client, et faire envoyer un message tapé au clavier de l'application serveur à l'application client qui le print dans la console. Ça c'est OK
    - Le truc c'est qu'un chat c'est dans deux sens, donc je suis un tutoriel sur les threads pour pouvoir envoyer ET recevoir à partir des deux applications. Donc je ne change rien à mon code à part que j'ajoute chez le client un thread pour envoyer et chez le serveur un thread pour recevoir. Je compile et PAF : maintenant le client envoie et le serveur reçoit, mais dans l'autre sens maintenant ça ne marche plus, alors que j'y ai rien touché...

    C'est surement un truc tout "con" (ça m'arrive tout le temps) mais je trouve pas ...



    Le code de l'application serveur :


    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
    #if defined (WIN32)
    #include <winsock2.h>
    typedef int socklen_t;
    #elif defined (linux)
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #define INVALID_SOCKET -1
    #define SOCKET_ERROR -1
    #define closesocket(s) close(s)
    typedef int SOCKET;
    typedef struct sockaddr_in SOCKADDR_IN;
    typedef struct sockaddr SOCKADDR;
    #endif
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <pthread.h>
    #define PORT 23
     
     
     
    int main(void)
    {
    #if defined (WIN32)
        WSADATA WSAData;
        int erreur = WSAStartup(MAKEWORD(2,2), &WSAData);
    #else
        int erreur = 0;
    #endif
     
        SOCKET sock;
        SOCKADDR_IN sin;
        SOCKET csock;
        SOCKADDR_IN csin;
        char buffer[100] = "Bonjour !";
        socklen_t recsize = sizeof(csin);
        int sock_err;
        pthread_t thread;
        void* sock_receive(SOCKET sock);
     
     
        /* Si les sockets Windows fonctionnent */
        if(!erreur)
        {
            sock = socket(AF_INET, SOCK_STREAM, 0);
     
            /* Si la socket est valide */
            if(sock != INVALID_SOCKET)
            {
                printf("La socket %d est maintenant ouverte en mode TCP/IP\n", sock);
     
                /* Configuration */
                sin.sin_addr.s_addr    = htonl(INADDR_ANY);   /* Adresse IP automatique */
                sin.sin_family         = AF_INET;             /* Protocole familial (IP) */
                sin.sin_port           = htons(PORT);         /* Listage du port */
                sock_err = bind(sock, (SOCKADDR*)&sin, sizeof(sin));
     
                /* Si la socket fonctionne */
                if(sock_err != SOCKET_ERROR)
                {
                    /* Démarrage du listage (mode server) */
                    sock_err = listen(sock, 5);
                    printf("Listage du port %d...\n", PORT);
     
                    /* Si la socket fonctionne */
                    if(sock_err != SOCKET_ERROR)
                    {
                        /* Attente pendant laquelle le client se connecte */
                        printf("Patientez pendant que le client se connecte sur le port %d...\n", PORT);
     
                        csock = accept(sock, (SOCKADDR*)&csin, &recsize);
                        printf("Un client se connecte avec la socket %d de %s:%d\n", csock, inet_ntoa(csin.sin_addr), htons(csin.sin_port));
                        pthread_create(&thread, NULL, sock_receive(csock), NULL);
                        printf("Debut des transmissions, que voulez vous envoyer?\n");
                        while (strstr(buffer, "/stop")==NULL)
                        {
                            fgets(buffer, 100, stdin);
                            sock_err = send(csock, buffer, 100, 0);
     
                            if(sock_err != SOCKET_ERROR)
                                printf("Chaine envoyée : %s\n", buffer);
                            else
                                printf("Erreur de transmission\n");
                        }
                        printf("fin des transmissions\n");
                        /* Il ne faut pas oublier de fermer la connexion (fermée dans les deux sens) */
                        shutdown(csock, 2);
                    }
                }
     
                /* Fermeture de la socket */
                printf("Fermeture de la socket...\n");
                closesocket(sock);
                pthread_cancel(thread);
                printf("Fermeture du serveur terminee\n");
            }
     
    #if defined (WIN32)
            WSACleanup();
    #endif
        }
     
        /* On attend que l'utilisateur tape sur une touche, puis on ferme */
        getchar();
     
        return EXIT_SUCCESS;
    }
     
    void* sock_receive(SOCKET sock)
    {
        char buffer2[100];
        while(1)
        {
            if(recv(sock, buffer2, 100, 0) != SOCKET_ERROR)
                printf("Recu : %s\n", buffer2);
        }
    }
    Le code de l'application client :
    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
    #if defined (WIN32)
        #include <winsock2.h>
        typedef int socklen_t;
    #elif defined (linux)
        #include <sys/types.h>
        #include <sys/socket.h>
        #include <netinet/in.h>
        #include <arpa/inet.h>
        #include <unistd.h>
        #define INVALID_SOCKET -1
        #define SOCKET_ERROR -1
        #define closesocket(s) close(s)
        typedef int SOCKET;
        typedef struct sockaddr_in SOCKADDR_IN;
        typedef struct sockaddr SOCKADDR;
    #endif
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <pthread.h>
    #define PORT 23
     
     
     
    int main(void)
    {
        #if defined (WIN32)
            WSADATA WSAData;
            int erreur = WSAStartup(MAKEWORD(2,2), &WSAData);
        #else
            int erreur = 0;
        #endif
     
        SOCKET sock;
        SOCKADDR_IN sin;
        char buffer[100] = "";
        char IP[30] = "";
        pthread_t thread;
        void* sock_send(SOCKET sock);
     
     
        /* Si les sockets Windows fonctionnent */
        if(!erreur)
        {
            /* Création de la socket */
            sock = socket(AF_INET, SOCK_STREAM, 0);
     
            /* Configuration de la connexion */
            printf("IP ? (127.0.0.1 pour ce pc)");
            fgets(IP, 30, stdin);
            sin.sin_addr.s_addr = inet_addr(IP);
            sin.sin_family = AF_INET;
            sin.sin_port = htons(PORT);
     
            /* Si l'on a réussi à se connecter */
            if(connect(sock, (SOCKADDR*)&sin, sizeof(sin)) != SOCKET_ERROR)
            {
                printf("Connection à %s sur le port %d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
                /* Si l'on reçoit des informations : on les affiche à l'écran */
                printf("debut de la reception\n");
                pthread_create(&thread, NULL, sock_send(sock), NULL);
                while(strstr(buffer, "/stop")==NULL)
                {
                    if(recv(sock, buffer, 100, 0) != SOCKET_ERROR)
                        printf("Recu : %s\n", buffer);
                }
            }
            /* sinon, on affiche "Impossible de se connecter" */
            else
            {
                printf("Impossible de se connecter\n");
            }
            printf("fin de reception\n");
            pthread_cancel(thread);
            /* On ferme la socket */
            closesocket(sock);
     
            #if defined (WIN32)
                WSACleanup();
            #endif
        }
     
        /* On attend que l'utilisateur tape sur une touche, puis on ferme */
        getchar();
     
        return EXIT_SUCCESS;
    }
    void* sock_send(SOCKET sock){
    char buffer2[100] = "";
    int sock_err;
    while(1){
    fgets(buffer2, 100, stdin);
    sock_err = send(sock, buffer2, 100, 0);
    if(sock_err != SOCKET_ERROR)
        printf("Chaine envoyée : %s\n", buffer2);
    else
        printf("Erreur de transmission\n");}}


    Merci d'avance !!!!!!


    Édit :
    Une petite question moins importante, pourquoi la connexion marche très bien en réseau local classique mais pas quand j'essaie de me connecter via un réseau "hamachi" ?

  2. #2
    Membre émérite
    Avatar de imperio
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2010
    Messages
    851
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2010
    Messages : 851
    Points : 2 293
    Points
    2 293
    Par défaut
    Oula, mauvaise comprehension des pointeurs sur fonction ! Je m'explique, cette ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    pthread_create(&thread, NULL, sock_receive(csock), NULL);
    Est incorrecte. Ca devrait etre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    pthread_create(&thread, NULL, sock_receive, &csock);
    Ensuite cette ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void* sock_receive(SOCKET sock)
    Est incorrecte aussi, ca devrait etre :

    void* sock_receive(void *sock)
    Apres tu castes ce void* en SOCKET* et le tour est joue. Cote client c'est carrement foireux, tu n'as pas de thread et tu "appelles" une fonction de maniere pourrie.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void* sock_send(SOCKET sock);
    On appelle une fonction de cette facon :

    Il te manque clairement les bases. Avant de t'attaquer aux threads et au reseau tu devrais reprendre les bases car tu ne les as clairement pas.

    Enfin derniere petite remarque :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char buffer2[100];
        while(1)
        {
            if(recv(sock, buffer2, 100, 0) != SOCKET_ERROR)
                printf("Recu : %s\n", buffer2);
        }
    Ce code est pourri. Pourquoi ? Si jamais tu n'as pas de '\0' a la fin de ton buffer ton programme risque de planter lamentablement. Ce qui demontre une fois de plus tes lacunes sur les bases de ce langage. Le bon code serait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    char buffer2[101];
    int ret;
     
        while(1)
        {
            if((ret = recv(sock, buffer2, 100, 0)) != SOCKET_ERROR)
               buffer2[ret] = 0; 
               printf("Recu : %s\n", buffer2);
        }

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    6
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 6
    Points : 5
    Points
    5
    Par défaut
    On va dire merci pour ton aide ...

    J'appliquerai tout ça quand j'aurai le temps et j'éditerai ce message.

Discussions similaires

  1. problème thread ne s'exécute pas correctement
    Par oumay dans le forum Débuter avec Java
    Réponses: 7
    Dernier message: 04/03/2010, 13h15
  2. [Thread]Problème de processus
    Par berg dans le forum Concurrence et multi-thread
    Réponses: 5
    Dernier message: 18/06/2005, 21h40
  3. Thread--> problème avec ThreadProc
    Par stof dans le forum MFC
    Réponses: 33
    Dernier message: 08/06/2005, 14h47
  4. Réponses: 5
    Dernier message: 19/04/2005, 09h50
  5. Problème à l'exécution avec wxWindows (compilé avec BCC55)
    Par ShootDX dans le forum Autres éditeurs
    Réponses: 5
    Dernier message: 14/11/2003, 19h04

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