#1 Le 08/01/2008, à 00:18
- anek971
client-serveur avec un pipe [Resolu]
Bonjour,
Je dois coder un programme de type client serveur ou un client doit envoyer 2 entier et le serveur doit lui renvoyer la somme des deux.
Seulement j'ai un message d'erreur du style write illegal seek je vois pas trop pourquoi.
Pourriez vous me mettre sur la voix:
Voici mon code
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
/*variables globale*/
int pid;//retourne le pid du fils
int tube[2];//tube avec les 2 descripteurs ecriture et lecture du tube
//tube[0] est le descripteur pour la lecture
//tube[1] est le descripteur pour l'ecriture
/*prototype fonction*/
void pere();
void fils();
/*fonction principale*/
int main()
{
pipe(tube);//creation du tube
switch(pid=fork())//pid prend le pid du fils et fork crée pere et fils
{
case -1:perror("fork");break; //en cas d'erreur
case 0:fils();break;//chez le fils
default:pere();break;//chez le pere
}
return 0;
}
/*fonction*/
/*fonction client*/
void pere()
{
int nbre[2];
int res=0;
int i;
printf("\n[pere] Ecrire 2 chiffres : ");
for(i=0;i<1;i++)
scanf("%d",&nbre[i]);
/*si on a pas ecrit 2 entier on ecrit l'erreur*/
if(write(tube[1],nbre,2)!=2*sizeof(int))
perror("[pere] write");
/*plus besoin d'ecrire*/
close(tube[1]);
/*on attend la fin de l'action du fils*/
wait(0);
printf("\n[pere] %d + %d = ",nbre[0],nbre[1]);
/*si on a pas un entier a lire on ecrit l'erreur*/
if(read(tube[0],&res,1)!=sizeof(int))
perror("[pere] read");
close(tube[0]);
}
/*fonction serveur*/
void fils()
{
int nbre[2];
int res=0;
/*si on ne lit pas 2 entier dans le tube*/
if(read(tube[0],nbre,2)!=2*sizeof(int))
perror("[fils] read");
/*je ferme le descripteur en lecture car je n'ai plus besoin de lire*/
close(tube[0]);
printf("\n[fils] j'ai recu %d et %d \n",nbre[0],nbre[1]);
res=nbre[0]+nbre[1];
printf("\n[fils] je dois retourner %d \n",res);
/*si on ecrit pas un entier dans le tube*/
if(write(tube[1],&res,1)!=sizeof(int))
perror("[fils] write");
close(tube[1]);
}
Resultat après test :
[pere] Ecrire 2 chiffres : 10
2
[pere] write: Success
[fils] read: Success
[fils] j'ai recu 9633802 et 134514496
[fils] je dois retourner 144148298
[fils] write: Illegal seek
[pere] read: Illegal seek
[pere] 10 + 2 =
A cela j'aurai quelques question a rajouter car je pense que mon gros probleme est de ne pas avoir bien saisi toute les notions que j'utilise dans la communication entre processus.
Si j'ai bien compris quand je crée un tube a l'aide de la fonction pipe, 2 descripteurs en ressortent un pour l'ecriture et l'autre pour la lecture.
Donc dans mon exemple tube[0] =>lecture et tube[1]=>ecriture pour le processus pere et aussi pour le fils.
Ensuite on introduit une notion dans mon cours disant que si il n' y a rien a lire read est bloquante.
Mais qu'entend on par bloquante? que si le pere ecrit par exemple le fils ne peut pas ecrire en meme temps?
Maintenant comment dire au fils de ne lire que lorsque le pere a finit donc dans mon cas que les 2 entiers ont été tapé
et de dire au pere de ne pas lire le résultat avant que le fils est finit de faire l'operation d'addition.
Ensuit dans mon enoncé on me dit que le serveur, donc le fils doit tourner en boucle mais si je le fais comment faire ?(j'imagine bien qu'il faut un wile(1) par exemple, mais si je fais ca comment le pere saura que c'est a son tour de lire les resultats.
Ca en fait des questions mais merci d'avances.
Dernière modification par anek971 (Le 09/01/2008, à 16:34)
Hors ligne
#2 Le 08/01/2008, à 00:44
- best_friend_fr
Re : client-serveur avec un pipe [Resolu]
Salut
Quelques precisions
Donc dans mon exemple tube[0] =>lecture et tube[1]=>ecriture pour le processus pere et aussi pour le fils.
Faux, c'est pour l'un ou pour l'autre. Si tu as commence a lire dans un pipe, tu ne peux plus ecrire dedans et vice versa. Si tu veux transmettre dans les 2 sens, il faut 2 pipes. Ta seek error vient de la je crois.
Mais qu'entend on par bloquante?
Que si il n'y a rien a lire, read attend sans rien faire jusqu'a ce qu'il y ait quelque chose qui arrive.
et de dire au pere de ne pas lire le résultat avant que le fils est finit de faire l'operation d'addition.
Le pere fait un read sur le bon pipe, et comme il n'y a rien, il va attendre que quelque chose arrive. Sinon, il faut utiliser la fonction select (pas utile ici).
Si tu alternes bien, ecrire 2 nombres, en ecrire 1..., tu ne devrais pas avoir de probleme de synchro.
sudo apt-get replace langage_sms by grammaire orthographe ponctuation
La documentation est avant tout faite pour ceux qui posent les questions, et non ceux qui y répondent
Best_friend_fr
Hors ligne
#3 Le 08/01/2008, à 10:25
- anek971
Re : client-serveur avec un pipe [Resolu]
Merci pour les réponses toutefois meme en créant un deuxieme tube j'ai le meme probleme :
En gros j'ai crée tube[2] et tube2[2], le premier va servir pour ecrire du pere vers le fils et l'autre du fils vers le pere.
J'ai quand meme les messages d'erreur cité plus haut.
Je montre mon code :
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
/*variables globale*/
int pid;//retourne le pid du fils
int tube[2];//tube du pere vers le fils
//tub[0] est le descripteur pour la lecture
//tube[1] est le descripteur pour l'ecriture
int tube2[2];//tube du fils vers le pere
/*prototype fonction*/
void pere();
void fils();
/*fonction principale*/
int main()
{
pipe(tube);//creation du tube pere vers le fils
pipe(tube2);//creation du tube fils vers le pere
//printf("\ntube lecture %d ecriture %d",tube[0],tube[1]);
//printf("\ntube2 lecture %d ecriture %d",tube2[0],tube2[1]);
switch(pid=fork())//pid prend le pid du fils et fork crée pere et fils
{
case -1:perror("fork");break; //en cas d'erreur
case 0:fils();break;//chez le fils
default:pere();break;//chez le pere
}
return 0;
}
/*fonction client*/
void pere()
{
int nbre[2];
int res=0;
int i;
printf("\n Ecrire 2 chiffres : ");
for(i=0;i<2;i++)
scanf("%d",&nbre[i]);
//tube pere vers le fils on ne lit pas on ecrit
close(tube[0]);
/*si on a pas ecrit les 2 chiffres erreur*/
if(write(tube[1],&nbre,2)!=2*sizeof(int))
perror("[pere tube] write");
/*plus besoin d'ecrire*/
close(tube[1]);
/*on attend la fin de l'action du fils qu'il est finit de faire le calcul*/
wait(0);
//printf("\n[pere] %d + %d = ",nbre[0],nbre[1]);
//dans le deuxieme tube le pere n'ecrit pas, il lit
close(tube2[1]);
/*si on a pas un entier a lire on ecrit l'erreur*/
if(read(tube2[0],&res,1)!=sizeof(int))
perror("[pere tube2] read");
//plus besoin de lire dans le deuxieme tube c'est finit
close(tube2[0]);
}
/*fonction serveur*/
void fils()
{
int nbre[2];
int x;
int res=0;
//dans le premier tube le fils ne fait que lire
close(tube[1]);
/*si on ne lit pas 2 entier dans le tube*/
if(read(tube[0],&nbre,2)!=2*sizeof(int))
perror("[fils tube] read");
//plus rien a lire
close(tube[0]);
printf("\n[fils] j'ai recu %d et %d \n",nbre[0],nbre[1]);
//on fait l'addition
res=nbre[0]+nbre[1];
printf("\n[fils] je dois retourner %d \n",res);
//on ne lit pas dans le deuxieme tube
close(tube2[0]);
/*si on ecrit pas un entier dans le tube*/
if(write(tube2[1],&res,1)!=sizeof(int))
perror("[fils tube2] write");
//on n'a plus rien a ecrire
close(tube2[1]);
}
Dernière modification par anek971 (Le 08/01/2008, à 19:15)
Hors ligne
#4 Le 08/01/2008, à 19:16
- best_friend_fr
Re : client-serveur avec un pipe [Resolu]
Salut
Autre probleme:
write et read prennent en 3e argument le nombre d'octets a ecrire ou lire, pas le nombre d'entiers. c'est ce qui fait que tu as des valeurs exotiques.
sudo apt-get replace langage_sms by grammaire orthographe ponctuation
La documentation est avant tout faite pour ceux qui posent les questions, et non ceux qui y répondent
Best_friend_fr
Hors ligne
#5 Le 08/01/2008, à 19:31
- anek971
Re : client-serveur avec un pipe [Resolu]
Ok je te remercie ca modifie tout donc au lieu de 1 j'ai mis sizeof(int) et c bon .
Sinon bon j'avais aussi oublier d'afficher le resultat mais merci je remet le code presque propre si ca peut aider quelq'un
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
/*variables globale*/
int pid;//retourne le pid du fils
int tube[2];//tube du pere vers le fils
//tub[0] est le descripteur pour la lecture
//tube[1] est le descripteur pour l'ecriture
int tube2[2];//tube du fils vers le pere
/*prototype fonction*/
void pere();
void fils();
/*fonction principale*/
int main()
{
pipe(tube);//creation du tube pere vers le fils
pipe(tube2);//creation du tube fils vers le pere
//printf("\ntube lecture %d ecriture %d",tube[0],tube[1]);
//printf("\ntube2 lecture %d ecriture %d",tube2[0],tube2[1]);
switch(pid=fork())//pid prend le pid du fils et fork crée pere et fils
{
case -1:perror("fork");break; //en cas d'erreur
case 0:fils();break;//chez le fils
default:pere();break;//chez le pere
}
return 0;
}
/*fonction client*/
void pere()
{
int nbre[2];
int res=0;
int i;
printf("\n Ecrire 2 chiffres : ");
for(i=0;i<2;i++)
scanf("%d",&nbre[i]);
//tube pere vers le fils on ne lit pas on ecrit
close(tube[0]);
/*si on a pas ecrit les 2 chiffres erreur*/
if(write(tube[1],&nbre,2*sizeof(int))!=2*sizeof(int))
perror("[pere tube] write");
/*plus besoin d'ecrire*/
close(tube[1]);
/*on attend la fin de l'action du fils qu'il est finit de faire le calcul*/
wait(0);
printf("\n[pere] %d + %d = ",nbre[0],nbre[1]);
//dans le deuxieme tube le pere n'ecrit pas, il lit
close(tube2[1]);
/*si on a pas un entier a lire on ecrit l'erreur*/
if(read(tube2[0],&res,sizeof(int))!=sizeof(int))
perror("[pere tube2] read");
//plus besoin de lire dans le deuxieme tube c'est finit
printf("%d",res);
close(tube2[0]);
}
/*fonction serveur*/
void fils()
{
int nbre[2];
int x;
int res=0;
//dans le premier tube le fils ne fait que lire
close(tube[1]);
/*si on ne lit pas 2 entier dans le tube*/
if(read(tube[0],&nbre,2*sizeof(int))!=2*sizeof(int))
perror("[fils tube] read");
//plus rien a lire
close(tube[0]);
printf("\n[fils] j'ai recu %d et %d \n",nbre[0],nbre[1]);
//on fait l'addition
res=nbre[0]+nbre[1];
printf("\n[fils] je dois retourner %d \n",res);
//on ne lit pas dans le deuxieme tube
close(tube2[0]);
/*si on ecrit pas un entier dans le tube*/
if(write(tube2[1],&res,sizeof(int))!=sizeof(int))
perror("[fils tube2] write");
//on n'a plus rien a ecrire
close(tube2[1]);
}
Encore merci, et je me permet de te poser ou de poser la question a tous, j'ai vu la primitive dup qui permet de dupliquer des descripteurs, mais je n'ai pas réellement compris l'utilité ou le but mise a part si on veut que l'entré de notre tube, crée a l'aide de pipe(le_tube) soit l'image de stdin(clavier) ou stdout(ecran).
Hors ligne
#6 Le 08/01/2008, à 19:36
- best_friend_fr
Re : client-serveur avec un pipe [Resolu]
Salut,
dup est utilise principalement pour rediriger les entrees et sorties standard (et les retablir).
J'admets ne jamais l'avoir utilise autrement et ne pas etre specialiste de la question.
sudo apt-get replace langage_sms by grammaire orthographe ponctuation
La documentation est avant tout faite pour ceux qui posent les questions, et non ceux qui y répondent
Best_friend_fr
Hors ligne
#7 Le 08/01/2008, à 19:37
- best_friend_fr
Re : client-serveur avec un pipe [Resolu]
Resolu dans le titre si tu es satisfait.
sudo apt-get replace langage_sms by grammaire orthographe ponctuation
La documentation est avant tout faite pour ceux qui posent les questions, et non ceux qui y répondent
Best_friend_fr
Hors ligne
#8 Le 08/01/2008, à 23:32
- anek971
Re : client-serveur avec un pipe [Resolu]
ok je veux bien fermer, la j'ai une question idiote comment on met resolu? je n'ai pas de liens ou bouton pour le fermer
et je n'ai pas acces au titre du sujet ?
Hors ligne
#9 Le 09/01/2008, à 00:24
- best_friend_fr
Re : client-serveur avec un pipe [Resolu]
Tu cliques sur modifier en bas du premier message.
sudo apt-get replace langage_sms by grammaire orthographe ponctuation
La documentation est avant tout faite pour ceux qui posent les questions, et non ceux qui y répondent
Best_friend_fr
Hors ligne