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 :

[Réseau] recv retourne -1


Sujet :

Réseau C

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 433
    Par défaut [Réseau] recv retourne -1
    Bonjour,

    Je fais des tests avant de commencer un projet réseau.
    J'ai un problème de communication entre mon serveur et mon client en mode TCP.
    Mon client envoie un message avec send et mon serveur est censé le récupérer avec recv.

    Voila le code coté 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
    /* Ici création socket, bind, listen */
    
        // On écoute un client
        csock = accept(sock, (SOCKADDR *)&csin, &sinsize);
        if(csock == INVALID_SOCKET) {
            perror("accept()");
            exit(errno);
        }printf("Accepter...\n");
    
    
        // Reception d'une donnée
        printf("Attente d'un message client...\n");
        if((n = recv(sock, buffer, sizeof buffer - 1, 0)) < 0) {
            perror("recv()");
            exit(errno);
        }
        buffer[n] = '\0';
        printf("Message recu: %s\n", buffer);
    Et coté 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
        SOCKET sock;
        struct hostent *hostinfo = NULL;
        SOCKADDR_IN sin = { 0 };
        const char *hostname = "192.168.0.5";
        char buffer[TAILLE_TAMPON] = "Ceci est un test de message.";
     
     
        // Création de la socket
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if(sock == INVALID_SOCKET) {
            perror("socket()");
            exit(errno);
        }
     
     
        // On récupère les informations de l'hôte auquel on veut se connecter
        hostinfo = gethostbyname(hostname);
        if (hostinfo == NULL) { // L'hôte n'existe pas
            fprintf (stderr, "Unknown host %s.\n", hostname);
            exit(EXIT_FAILURE);
        }
     
        // On remplis la structure pour se connecter
        sin.sin_addr = *(IN_ADDR *) hostinfo->h_addr; /* l'adresse se trouve dans le champ h_addr de la structure hostinfo */
        sin.sin_port = htons(PORT); /* on utilise htons pour le port */
        sin.sin_family = AF_INET;
     
        if(connect(sock,(SOCKADDR *) &sin, sizeof(SOCKADDR)) == SOCKET_ERROR) {
            perror("connect()");
            exit(errno);
        }
     
     
        // Envoie d'une donnée
        if(send(sock, buffer, strlen(buffer), 0) < 0) {
            perror("send()");
            exit(errno);
        }
        printf("Message envoyer: %s\n", buffer);
    La trace du programme donne coté serveur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    En ecoute...
    Essai d'acceptation...
    Accepter...
    Attente d'un message client...
    recv(): No error
     
    Process returned 0 (0x0)   execution time : 24.203 s
    Press any key to continue.
    Et coté client:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Message envoyer: Ceci est un test de message
    Après test je voie que le retour du recv est -1 (n=-1).
    Comment résoudre/diagnostiquer le problème ?

    Merci.

  2. #2
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par FabaCoeur Voir le message
    Je fais des tests avant de commencer un projet réseau.
    J'ai un problème de communication entre mon serveur et mon client en mode TCP.
    Mon client envoie un message avec send et mon serveur est censé le récupérer avec recv.
    Le code posté a l'air correct. Le problème est donc ailleurs. Poste le code complet du client et du serveur

  3. #3
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 433
    Par défaut
    Ca doit probablement provenir des magouilles que j'ai ajouté pour la portabilité Windows/Linux...
    J'ai trouvé les bouts de code sur un cours dans Developpez.net
    Je pense que ça ne conviens pas car j'inclus reseau.c au lieu de reseau.h, mais si je ne fais pas comme ça je ne peux pas compiler.
    D'autant plus que je ne comprends pas trop le mot clé "static".
    Merci d'avoir la patience de regarder dans le code !

    Voila le main.c:

    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
    #include <stdio.h>
    #include <stdlib.h>
     
    #include "reseau.c"
     
    int main() {
     
        // Début utilisation du réseau
        reseau_init();
     
        // Algorithme principal
    	// Ici je change pour compiler le client ou le serveur
        serveur();
    	//client();
     
        // Fin utilisation du réseau
        reseau_end();
     
        return 0;
    }
    reseau.h
    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
     
    #ifndef RESEAU_H
    #define RESEAU_H
     
     
    #ifdef WIN32
     
    #include <winsock2.h>
     
    #elif defined (linux)
     
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h> /* close */
    #include <netdb.h> /* gethostbyname */
    #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;
    typedef struct in_addr IN_ADDR;
     
    #else
     
    #error not defined for this platform
     
    #endif
     
    static void reseau_init(void);
    static void reseau_end(void);
     
     
    #endif /* guard */
    reseau.c
    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
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <errno.h>
    #include <string.h>
     
    #include "reseau.h"
     
     
    static void reseau_init(void)
    {
    #ifdef WIN32
       WSADATA wsa;
       int err = WSAStartup(MAKEWORD(2, 2), &wsa);
       if(err < 0)
       {
          puts("WSAStartup failed !");
          exit(EXIT_FAILURE);
       }
    #endif
    }
     
    static void reseau_end(void)
    {
    #ifdef WIN32
       WSACleanup();
    #endif
    }
    client.c
    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
    #include <stdio.h>
    #include <stdlib.h>
     
    #include "reseau.h"
     
     
    int client() {
     
        SOCKET sock;
        struct hostent *hostinfo = NULL;
        SOCKADDR_IN sin = { 0 };
        const char *hostname = "192.168.0.5"; // IP du serveur
        char buffer[1024] = "Ceci est un test de message.";
     
     
        // Création de la socket
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if(sock == INVALID_SOCKET) {
            perror("socket()");
            exit(errno);
        }
     
     
        // On récupère les informations de l'hôte auquel on veut se connecter
        hostinfo = gethostbyname(hostname);
        if (hostinfo == NULL) { // L'hôte n'existe pas
            fprintf (stderr, "Unknown host %s.\n", hostname);
            exit(EXIT_FAILURE);
        }
     
        // On remplis la structure pour se connecter
        sin.sin_addr = *(IN_ADDR *) hostinfo->h_addr; /* l'adresse se trouve dans le champ h_addr de la structure hostinfo */
        sin.sin_port = htons(PORT); /* on utilise htons pour le port */
        sin.sin_family = AF_INET;
     
        if(connect(sock,(SOCKADDR *) &sin, sizeof(SOCKADDR)) == SOCKET_ERROR) {
            perror("connect()");
            exit(errno);
        }
     
     
        // Envoie d'une donnée
        if(send(sock, buffer, strlen(buffer), 0) < 0) {
            perror("send()");
            exit(errno);
        }
        printf("Message envoyer: %s\n", buffer);
     
     
        // Fermeture sockets
        closesocket(sock);
     
        system("PAUSE");
     
        return 0;
    }
    serveur.c
    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
     
    #include <stdio.h>
    #include <stdlib.h>
     
    #include "reseau.h"
     
     
    int serveur() {
     
        SOCKET sock;
        SOCKADDR_IN sin = { 0 };
        char buffer[1024];
     
        SOCKET csock;
        SOCKADDR_IN csin = { 0 };
        int sinsize = sizeof csin;
        int n;
     
     
        // Création de la socket
        sock = socket(AF_INET, SOCK_STREAM, 0);
        if(sock == INVALID_SOCKET) {
            perror("socket()");
            exit(errno);
        }
     
     
        // On renseigner pour binder la socket
        sin.sin_addr.s_addr = htonl(INADDR_ANY); // Le serveur accepte toutes les adresses
        sin.sin_family = AF_INET;
        sin.sin_port = htons(PORT);
     
        if(bind (sock, (SOCKADDR *) &sin, sizeof sin) == SOCKET_ERROR) {
            perror("bind()");
            exit(errno);
        }
     
     
        // On écoute les connexions client
        printf("En ecoute...\n");
        if(listen(sock, NB_JOUEUR_MAX) == SOCKET_ERROR) {
            perror("listen()");
            exit(errno);
        }
     
     
        // On écoute un client
        csock = accept(sock, (SOCKADDR *)&csin, &sinsize);
        if(csock == INVALID_SOCKET) {
            perror("accept()");
            exit(errno);
        }printf("Accepter...\n");
     
     
        // Reception d'une donnée
        printf("Attente d'un message client...\n");
        if((n = recv(sock, buffer, sizeof buffer - 1, 0)) < 0) {
            perror("recv()");
            exit(errno);
        }
        buffer[n] = '\0';
        printf("Message recu: %s\n", buffer);
     
     
        // Fermeture sockets
        closesocket(sock);
        closesocket(csock);
     
        system("PAUSE");
     
        return 0;
    }

  4. #4
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    Ca doit probablement provenir des magouilles que j'ai ajouté pour la portabilité Windows/Linux ...
    Exact. Tu utilises errno pour le traitement des erreurs alors que sous Windows c'est WSAGetLastError (GetLastError) qu'il faut appeler. L'erreur 10057 correspond à "socket is not connected" (on récupère cette chaîne avec FormatMessage ou Error Lookup qui est fourni avec Visual Studio, ou encore Google ). En effet, c'est csock (le socket retourné par accept) qu'il faut passer à recv et non sock (le socket serveur). Je n'ai pas testé ton programme client (j'ai utilisé telnet comme client ...).

    Concernant l'organisation de tes fichiers, c'est le bordel en effet. On n'inclus pas un .c, seulement les .h. Mets un peu de l'ordre dès que tu pourras.

    D'autant plus que je ne comprends pas trop le mot clé "static".
    A quoi sert le mot-clé static ?

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 433
    Par défaut
    Ha bien vu, le recvfrom ne se fait pas sur la bonne socket !
    J'étais complètement passé à travers. Encore une victime du copié/collé !

    Je vais essayer de supprimer les mots clés statics et inclure les .h comme je fais avec toutes les fonctions, ça devrait passer. L'idée à la base c'était juste de faire totale abstraction de ces fonctions qui servent juste à la portabilité...

    Pour ce qui est des erreurs, je vais utiliser des printf tout simplement. Là j'utilisais errno car en copiant collant le code je pensais plus respecter les normes mais bon... moi ce que je veux c'est que ça tourne ^^

    Merci de coup de main, j'essaye tout ça ce soir

  6. #6
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    Là j'utilisais errno car en copiant collant le code je pensais plus respecter les normes mais bon ...
    Le domaine des réseaux n'est pas couvert par la norme. C'est déjà de la programmation système et dans ce domaine, la norme sous Windows c'est MSDN et sous les unixoïdes POSIX .

  7. #7
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par FabaCoeur Voir le message
    Merci d'avoir la patience de regarder dans le code !
    En essayant le code du serveur et du client en local (127.0.0.1), dans 2 threads d'un même processus, et en passant 5 à listen(), j'obtiens :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    WIN: winsock2: OK
    SIM: Appuyer sur ENTER pour lancer le client
    En ecoute...
     
    Message envoyer: Ceci est un test de message.
    Accepter...
    Attente d'un message client...
    recv(): No error
     
    Process returned 0 (0x0)   execution time : 2.577 s
    Press any key to continue.
    Effectivement, le problème concerne le socket passé à recv().

    Ceci fonctionne :

    http://delahaye.emmanuel.free.fr/forums/faba/

  8. #8
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 433
    Par défaut
    C'est bon le code que j'avais posté marche bien.
    Tant de temps perdu à cause d'une si petite erreur... erf

    Mais là me viens une question intéressante: comment faire pour tester les applications réseau avec un seul ordinateur? Jusqu'a maintenant, j'ai testé avec mes deux PC, l'un pour le client et l'autre pour le serveur. Comment faire pour tester le tout sur la même machine ? Comment faire même avec plusieurs clients et un serveur ?

    La réponse pourrait beaucoup m'aider dans le développement du projet.
    Je n'ai pas trop compris comment tu as fait, pourrait-tu approfondir ?

    Merci

  9. #9
    Rédacteur

    Avatar de ram-0000
    Homme Profil pro
    Consultant en sécurité
    Inscrit en
    Mai 2007
    Messages
    11 517
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Consultant en sécurité
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mai 2007
    Messages : 11 517
    Par défaut
    c'est pour cela qu'ils ont inventé 127.0.0.1 qui est l'adresse locale. Ainsi, tu peux lancer un serveur et plusieurs clients sur la même machine (enfin, c'est ce que je fais pour tester au début)
    Raymond
    Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi

    Cafuro Cafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
    e-verbe Un logiciel de conjugaison des verbes de la langue française.

    Ma page personnelle sur DVP
    .

  10. #10
    Membre éclairé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    433
    Détails du profil
    Informations personnelles :
    Âge : 38
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 433
    Par défaut
    Erf carrément bon à savoir tout ça !
    Merci pour toutes vos réponses

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

Discussions similaires

  1. Réseau Win/Linux
    Par ben91 dans le forum Développement
    Réponses: 2
    Dernier message: 08/09/2002, 22h59
  2. Comment subsituer un chemin par un autre dans un réseau ?
    Par Baillard dans le forum Développement
    Réponses: 3
    Dernier message: 11/08/2002, 14h01
  3. [Manip de fichiers] Fonction retournant des infos
    Par sans_atouts dans le forum C
    Réponses: 3
    Dernier message: 24/07/2002, 14h16
  4. Redimensionnement des Paquets IP sur un Réseau Local
    Par Bonoboo dans le forum Développement
    Réponses: 2
    Dernier message: 12/07/2002, 15h40

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