Précédent   Forum du club des développeurs et IT Pro > C et C++ > C
C Forum d'entraide technique sur le langage C. Avant de poster -> F.A.Q. C, Avant de poster.
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 03/01/2013, 11h29   #1
Damien3193
Invité de passage
 
Inscription : 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 !!
Damien3193 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/01/2013, 13h23   #2
Obsidian
Modérateur
 
Avatar de Obsidian
 
Homme
Chercheur d'emploi
Inscription : septembre 2007
Messages : 4 610
Détails du profil
Informations personnelles :
Sexe : Homme
Âge : 36
Localisation : France, Essonne (Île de France)

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

Informations forums :
Inscription : septembre 2007
Messages : 4 610
Points : 11 065
Points : 11 065
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.
Obsidian est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/01/2013, 11h33   #3
coco673
Invité régulier
 
Homme
Étudiant
Inscription : novembre 2012
Messages : 9
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Finlande

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : novembre 2012
Messages : 9
Points : 5
Points : 5
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);
  }
coco673 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 05/01/2013, 15h30   #4
Damien3193
Invité de passage
 
Inscription : 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 ^^
Damien3193 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 07/01/2013, 12h28   #5
coco673
Invité régulier
 
Homme
Étudiant
Inscription : novembre 2012
Messages : 9
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : Finlande

Informations professionnelles :
Activité : Étudiant

Informations forums :
Inscription : novembre 2012
Messages : 9
Points : 5
Points : 5
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
coco673 est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 05h59.


 
 
 
 
Partenaires

Hébergement Web