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

C Discussion :

Envoi sur tube "tmp", write(), read()


Sujet :

C

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

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4
    Points : 4
    Points
    4
    Par défaut Envoi sur tube "tmp", write(), read()
    Salut à tous !

    Bon voilà j'ai un problème sur lequel je me casse la tête depuis quelques jours déjà et la date de remise du TP approche à grand pas !

    Voici la consigne de mon exercice :
    Écrire deux programmes en C qui communiquent par le tube "tmp" crée précédemment. Le premier programme doit écrire dans le tube des nombres aléatoires entre 30 et 99 (sous forme de texte - 2 caractères). Le deuxième programme doit récupérer les nombres et écrire sur la sortie standard les caractères ASCII correspondants au codes numériques. (Note: vous pouvez utiliser les fonctions sprintf et itoa pour les conversions.)

    J'ai donc deux fichiers :
    Envoi.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
     
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <signal.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <sys/stat.h>
    #include <fcntl.h>
     
    int main(int argc, char *argv[])
    	{
    	int tube[2];
    	int chifRand=0;
    	int i=0;
    	//char chaine[256];
    	pipe(tube);
    	int df = open("tmp", O_APPEND|O_RDWR);
     
        	close (tube[0]);
    	while (i<10) {
    		chifRand = (rand() % (99-30 +1)) + 30;
    		//sprintf(chaine,"%d",chifRand);
    		printf("%i\n",chifRand);
    		write (df, /*chaine*/ &chifRand, 2);
    		i++;
    	}
     
    	return 0;
    	}
    Ce fichier permet donc l'envoi de nombres aléatoires sur un tube "tmp" que j'ai déjà créé.
    Je le suis tâté à utiliser "sprintf" pour résoudre le problème que je vais énoncer mais j'ai tout remis en com'.

    J'ai également reception.c permettant la réception de ces nombres :

    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 <string.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <signal.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <sys/stat.h>
    #include <fcntl.h>
     
    int main(int argc, char *argv[])
    {
    int tube[2];
    int buf;
    int i=0;
    pipe(tube);
    int df = open("tmp", O_APPEND|O_RDWR);
    close (tube[1]);
     
    while (i<10) {
    	read (df, &buf, 2);
    	printf ("%i bien recu \n", buf);
    	i++;
    }
     
    return 0;
    }
    Et voici enfin mon problème, lors de l'exécution :
    envoi.c :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    damien@damien-VirtualBox ~/Bureau/TP5-3.0/Exercice4 $ ./Envoi 
    73
    76
    67
    35
    73
    75
    96
    32
    59
    61
    reception.c :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    damien@damien-VirtualBox ~/Bureau/TP5-3.0/Exercice4 $ ./Reception 
    -1218969527 bien recu 
    -1218969524 bien recu 
    -1218969533 bien recu 
    -1218969565 bien recu 
    -1218969527 bien recu 
    -1218969525 bien recu 
    -1218969504 bien recu 
    -1218969568 bien recu 
    -1218969541 bien recu 
    -1218969539 bien recu
    Comme vous le voyez ça correspond pas des masses

    Je suppose que mon erreur viens du fait que j'envoi l'adresse des entiers et non les entiers eux-mêmes ...
    Je suppose également que la solution réside dans itoa() ou sprintf(), mais je ne vois pas du tout comment l'adapter à mon problème !

    Merci d'avance de votre aide !!

  2. #2
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 360
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 360
    Points : 23 600
    Points
    23 600
    Par défaut
    Bonjour et bienvenue,

    Ton problème se situe dans l'émetteur :

    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    		//sprintf(chaine,"%d",chifRand);
    		printf("%i\n",chifRand);
    		write (df, /*chaine*/ &chifRand, 2);

    Si tu utilises « printf() », tes données seront envoyées vers la sortie standard, donc à l'écran. Ça marche, mais ce n'est pas du tout ce que tu veux. Pourtant, la solution avec « chaine » et « sprintf » que tu as écrite était exactement la bonne, par rapport à l'énoncé.

    À la place, tu choisis d'envoyer le contenu d'une variable int quitte à la transcrire de l'autre côté. Certes, mais tu continues de passer la valeur « 2 » à write, ce qui ne correspond pas, en mémoire, à la taille d'un int. Tu ne transmets donc son contenu que partiellement. Comme tu travailles probablement sur une machine en big endian (un PC), tu envoies quand même l'essentiel, mais ce ne sera pas le cas partout.

    Côté client, tu récupères la valeur dans un int (« buf ») mais sans l'initialiser à zéro au départ ! Sa valeur est donc indéfinie et même si tu le renseignes bien avec ce que tu reçois, comme tu ne le remplis pas, ce qui reste dedans forme au final une valeur indéfinie.

    La solution consiste donc à rétablir ton « sprintf, write "chaine" » du côté émetteur, à déclarer un buffer « buf » de TROIS caractères, le dernier servant au zéro final : char buf[3] = { 0,0, '\0' };, et à y déposer à chaque fois les DEUX caractères que tu lis en provenance de ton tube, sans écraser le terminateur.

    Tu pourras ensuite faire directement un printf("%s",buf); pour en voir le contenu.

    Bon courage.

  3. #3
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2012
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2012
    Messages : 10
    Points : 10
    Points
    10
    Par défaut
    Bonjour j'ai le même problème sur mes tubes en fait je travaille sur un projet de client/serveur mais la reception des données via mon tube de retour ne me renvoi pas les mêmes données que chez le serveur comme toi Damien3193 à la place de mes donnée j'ai le droit à (null) pour chaque valeur que je demande j'ai bien vérifié la taille des données à écrire je pense qu'elle est bonne je ne vois absolument pas d'ou vient le problème pouvez vous m'aider ? merci

    voici mon 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
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    #include "cs.h"
     
    /***************************************************
     ********************CLIENT.C***********************
     **************************************************/
     
    int main (int argc, char* arg[]) {  
      struct Request req;
      int fd,fdc;
      int n; 
      //On recupere le pid pour en faire le nom du tube de retour
      sprintf(req.pidRequete, "tube%d", getpid()); 
     
      //Creation du tube de retour
      if(mkfifo(req.pidRequete, S_IRUSR | S_IWUSR) == -1 ) {
        perror("mkfifo");
        exit(EXIT_FAILURE);
      }
     
      //Ouverture du tube du serveur en ecriture 
      if ((fd = open(TUBER, O_WRONLY)) == -1){
        perror("openClient");
        exit(EXIT_FAILURE);
      }
    /****************Envoi de la requete***********************/
     req.type_request = 1;
     printf("%u\n",getuid());
     req.infoProc.uidUsr = getuid();
     if (write(fd, &req, sizeof(req)) == -1) {
      perror("write");
      exit(EXIT_FAILURE);
     }
     /****************Fin de l envoi****************************/
     
    //Ouverture du tube de reponse en lecture et attente de la reponse                                     
     if ((fdc = open(req.pidRequete, O_RDONLY)) == -1 ) {
       perror("open");
       exit(EXIT_FAILURE);
     }
     
       //lecture de la reponse
       union Answer reqback;
       if((n=read(fdc ,&reqback, sizeof(reqback))) == -1){
         perror("read");
         exit(EXIT_FAILURE);
       } 
       //traitement de la reponse
       if (reqback.usrInfo.uidInfo != NULL || reqback.usrInfo.grpInfo != NULL) {
         fprintf(stdout,"Login : %s | Nom réel : %s | rep : %s | shell : %s\n",reqback.usrInfo.uidInfo->pw_gecos,reqback.usrInfo.uidInfo->pw_name,reqback.usrInfo.uidInfo->pw_dir,reqback.usrInfo.uidInfo->pw_shell);
        printf("Grp NAme : %s\n",reqback.usrInfo.grpInfo->gr_name);
     }
     
     //fermeture des descripteurs
     if(close(fd) == -1) {
       perror("close");
       exit(EXIT_FAILURE);
     }
     if(close(fdc) == -1) {
       perror("close");
       exit(EXIT_FAILURE);
     }
     //femeture du tube de retour 
     if(unlink(req.pidRequete) == -1) {
       perror("unlink");
       exit(EXIT_FAILURE);
     }
     exit(EXIT_SUCCESS);
    }
    et la mon 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
    73
    74
    75
    76
    77
    78
    79
    void serveurTube(){
      int fd, n;
      int fdBack;
      struct Request req;
      int status;
     
      //Creation du tube pour recuperer la requete
      if(mkfifo(TUBER, S_IRUSR | S_IWUSR ) == -1) {
        perror("mkfifo1");
        exit(EXIT_FAILURE);
      }
      //ouverture de tube serveur en lecture (attente requete)                                   
      if ((fd = open(TUBER, O_RDONLY)) == -1) {
        perror("open");
        exit(EXIT_FAILURE);
      }
      switch(fork()) {
      case -1 :
        perror("fork");
        exit(EXIT_FAILURE);
        break;
      case 0 :;
        //lecture de la requete
        n = read(fd, &req, PIPE_BUF);
        if(n == -1) {
          perror("read");
          exit(EXIT_FAILURE);
        }
     
        printf("le nom du tube de retour est %s\n",req.pidRequete);
        printf("le type de req est %i\n",req.type_request);
        union Answer reqBack;
     
        //traitement de la requete
        switch(req.type_request) {
        case 1 : 
          if( (reqBack.usrInfo.uidInfo =getpwuid(req.infoProc.uidUsr)) == NULL) {
    	perror("uid");
    	exit(EXIT_FAILURE);
          }    
          if ((reqBack.usrInfo.grpInfo = getgrgid(req.infoProc.uidUsr)) == NULL ) {
    	perror("gid");
    	exit(EXIT_FAILURE);
          }
          break;
        case 2 : 
          reqBack.procInfo = caracteristique(req.infoProc.pidProc);
          printf("2\n");
          break;
        default :
          fprintf(stderr,"Requete Incorrect : 1 = info User\n 2 = info Processus\n");
          exit(EXIT_FAILURE);
        }
        //ouverture du tube de retour en ecriture     
        if ((fdBack = open(req.pidRequete, O_WRONLY)) == -1) {
          perror("open2");
          exit(EXIT_FAILURE);
        }
        printf("ouver\n");
        //Ecriture dans le tube de retour des donnees a afficher
        if (write(fdBack, &reqBack, sizeof(reqBack)) == -1) {
          perror("write");
          exit(EXIT_FAILURE);
        }
        printf("cest ecrit\n");
        //Fermeture du descripteur sur le tube de retour
        if(close(fdBack) == -1){
          perror("close");
          exit(EXIT_FAILURE);
        }
        break;
      default : 
        if(wait(&status) == -1){
          perror("wait");
          exit(EXIT_FAILURE);
        }
      }
        exit(EXIT_SUCCESS);
      }

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

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4
    Points : 4
    Points
    4
    Par défaut Merci :)
    Je vais tester ta solution, je n'ai pas le temps aujourd'hui mais sans doute demain !

    Merci de votre aide ^^

  5. #5
    Membre à l'essai
    Homme Profil pro
    Étudiant
    Inscrit en
    Novembre 2012
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Novembre 2012
    Messages : 10
    Points : 10
    Points
    10
    Par défaut
    Pour ceux qui auront le même problème la provenance de cette erreur est que dans ma structure de retour j'utilisais des pointeurs qui n'étais ce qui provoquait des erreurs d'adressage à la sortie du tube je suppose et ma solution aura été de transformer mes variables de type passwd* en tableau de char et ça marche niquel ! a bientôt

Discussions similaires

  1. [Quote] DVP quoté sur Bashfr
    Par Skyounet dans le forum La taverne du Club : Humour et divers
    Réponses: 16
    Dernier message: 26/09/2006, 19h52
  2. Problème sur Request.ServerVariables("QUERY_STRING"
    Par PrinceMaster77 dans le forum ASP
    Réponses: 3
    Dernier message: 25/03/2005, 12h47

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