+ Répondre à la discussion
Affichage des résultats 1 à 5 sur 5
  1. #1
    Invité de passage
    Inscrit en
    décembre 2012
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : décembre 2012
    Messages : 4
    Points : 0
    Points
    0

    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 :
    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 :
    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 :
    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 :
    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
    Responsable Modération
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    septembre 2007
    Messages
    5 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : septembre 2007
    Messages : 5 515
    Points : 14 177
    Points
    14 177

    Par défaut

    Bonjour et bienvenue,

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

    Code C :
    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
    Invité régulier
    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 : 5
    Points
    5

    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 :
    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 :
    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
    Invité de passage
    Inscrit en
    décembre 2012
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : décembre 2012
    Messages : 4
    Points : 0
    Points
    0

    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
    Invité régulier
    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 : 5
    Points
    5

    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

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •