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 :

Comportement (aléatoire?) de send()/recv() ?


Sujet :

Réseau C

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 4
    Points : 4
    Points
    4
    Par défaut Comportement (aléatoire?) de send()/recv() ?
    Bonjour,

    J'essaie de comprendre les bases de l'utilisation des sockets en codant un serveur et un client minimaux en c++.

    Le serveur crée un thread de communication avec chaque nouveau client, avec une boucle attendant les messages ( recv() avec un(e) socket en mode bloquant.

    Un client peut envoyer un message au serveur via une fonction simple contenant un send() qui utilise un(e) socket bloquante.

    Le mode de communication est connecté.

    Les deux impriment ce qu'ils envoient / reçoivent sur la sortie standard.

    Le client se connecte correctement.

    Mon probleme vient du fait que si j'appelle 3 fois (par exemple) la fonction d'envoi de message du client, le serveur va recevoir 3 messages identiques à ceux envoyés (3 recv() à la suite) et c'est le comportement attendu, OU BIEN, avec les 2 mêmes exécutables, le serveur va recevoir 1 message contenant les 3 envoyés par le client.

    voici une sortie:
    Serveur recoit :Message test 1Message test 2Message test 3
    42 bytes recus

    une autre:
    Serveur recoit :Message test 1
    14 bytes recus
    Serveur recoit :Message test 2
    14 bytes recus
    Serveur recoit :Message test 3
    14 bytes recus

    Apres plusieurs essais, je me rend compte que lorsque je viens de compiler le client, le serveur imprime le resultat attendu. Si je relance le serveur et le client, la mauvaise sortie est obtenue (42 bytes consécutifs). Si je recompile le client, j'ai a nouveau la bonne sortie...etc

    Voici le code de la boucle de reception du 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
     
    do{
    	memset(message, 0, MAX_MESSAGE_LEN);
            res = recv(soc, message, sizeof message - 1, 0);
            if(res > 0){
                cout << "Serveur recoit :" << message << endl;
            }else if(res == 0){
                cout << "Connection lost" << endl;
            }else{
                cerr << "Serveur:Erreur reception de message" << endl;
            }
            cout << res << " bytes recus" << endl;
        }while(res > 0);
    Voici la fonction d'envoi du client:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    void Client::sendMessage(string m){
        const char * msg = m.c_str();
        cout << "Client envoie:" << msg << endl;
        int res;
        res = send(communicationSocket, msg, (int)strlen(msg), 0);
    	if(res < 0){
    	    cerr << "Client : erreur d'envoi de message" << endl;
    	}
    	cout << res << " bytes envoyés" << endl;
    }
    Et voila une partie du main:
    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
     
        Serveur s;
        Client c;
        if(isServeur){
            if(s.init()){
                cerr << "erreur init serveur" << endl;
            }
            if(s.start()){
                cerr << "erreur demarrage serveur" << endl;
            }
        }else{
            if(c.init()){
                cerr << "erreur init client" << endl;
            }else{
                cout << "client initialisé" << endl;
                c.connectToServer(SERVER_ADDR);
            }
            c.sendMessage("Message test 1");
            c.sendMessage("Message test 2");
            c.sendMessage("Message test 3");
        }
    Quelqu'un peut-il m'éclairer sur ce qui me semble être un grand mystère?

    Merci d'avance!

  2. #2
    Membre averti Avatar de Jenna
    Inscrit en
    Décembre 2009
    Messages
    272
    Détails du profil
    Informations personnelles :
    Âge : 39

    Informations forums :
    Inscription : Décembre 2009
    Messages : 272
    Points : 339
    Points
    339
    Par défaut
    Rien ne garantit 1 send pour 1 recv

    des fois tu auras 1 send pour 3 recv

    d'autre fois, tu auras 3 send pour 1 recv

    tu ne peux pas prévoir.

    C'est à toi de synchroniser l'émetteur et le récepteur

    Le protocole le plus simple, c'est l'émetteur envoie toujours le même nombre d'octets dans une trame, ainsi le récepteur sait combien il doit en recevoir.

    Un protocole plus élaboré est que l'émetteur envoie toujours en premier la longueur de la trame qu'il va envoyer ensuite. Le récepteur recoit la longueur et ensuite fait un recv sur cette longueur.

    Un autre protocole est d'utiliser un caractère spécial de fin de trame (le caractère \n par exemple). Le récepteur reçoit les données tant qu'il n'a pas reçu ce caractère. Ce modèle est plus adapté pour les trames qui ne transportent que du texte ASCII (FTP ou HTTP par exemple)
    La valeur n'attend pas le nombre des années

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 4
    Points : 4
    Points
    4
    Par défaut
    Merci pour la réponse!

    Effectivement je vais utiliser une de tes solutions afin de synchroniser les envois/receptions.

    Toutefois rien n'est dit sur ce sujet dans les pages man de ces fonctions, et je me demande toujours pourquoi de telles fonctions surement déterministes ont un comportement "apparement" non déterministe?

  4. #4
    Inactif  
    Avatar de Mac LAK
    Profil pro
    Inscrit en
    Octobre 2004
    Messages
    3 893
    Détails du profil
    Informations personnelles :
    Âge : 49
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Octobre 2004
    Messages : 3 893
    Points : 4 846
    Points
    4 846
    Par défaut
    Citation Envoyé par grip.inc Voir le message
    je me demande toujours pourquoi de telles fonctions surement déterministes ont un comportement "apparement" non déterministe?
    La fontion elle-même ne l'est pas : déterministe, en informatique, cela veut dire que l'on sait très exactement ce que va faire la fonction ainsi qu'en combien de temps elle le fera.

    Or, send n'est pas déterministe : tu es limité / conditionné par la taille des buffers de la pile TCP/IP, les accès au réseau Ethernet (CSMA/CD), et la période de traitement de la pile (qui peut "attendre" des données supplémentaires pour éviter d'envoyer un paquet trop petit, notamment).

    Et du coup, recv ne peut pas l'être non plus, car l'émetteur a pu attendre plusieurs millisecondes avant d'émettre un paquet, et du coup grouper plusieurs envois unitaires en un seul paquet... Ou au contraire, séparer un envoi trop volumineux en plusieurs paquets de taille convenable.
    Mac LAK.
    ___________________________________________________
    Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.

    Sources et composants Delphi sur mon site, L'antre du Lak.
    Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.

    Rejoignez-nous sur : Serveur de fichiers [NAS] Le Tableau de bord projets Le groupe de travail ICMO

  5. #5
    Candidat au Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 4
    Points : 4
    Points
    4
    Par défaut
    Merci pour la réponse, je passe en résolu!

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 18/02/2015, 18h06
  2. conflit send recv socket
    Par gy0m76 dans le forum Réseau
    Réponses: 3
    Dernier message: 06/02/2007, 15h10
  3. send, recv, udp, packet ?
    Par NONOCE dans le forum Développement
    Réponses: 4
    Dernier message: 12/01/2007, 11h13
  4. [Socket] Send/Recv type double sur architectures différentes
    Par nicolas.pied dans le forum Réseau
    Réponses: 4
    Dernier message: 31/03/2006, 20h33
  5. Comportement aléatoire du programme
    Par afrikha dans le forum Agents de placement/Fenêtres
    Réponses: 9
    Dernier message: 12/12/2005, 15h15

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