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

Linux Discussion :

[IPC] File de messages


Sujet :

Linux

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    59
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 59
    Points : 124
    Points
    124
    Par défaut [IPC] File de messages
    Bonjour;

    Dans le cadre d'un projet, je suis amené à faire communiqué deux applications à l'aide de file de message. Avant de complexifier le programme pour l'adapter aux réels besoin, j'aimerai simplement faire :
    - Le premier programme dépose un message dans la liste
    - Le second boucle infini est affiche les message au fur et à mesure de leurs arrivés sur cette même file.

    Pourtant impossible de faire quelque chose qui marche. Les exemples sur Internet ne sont pas légion et ceux que j'ai trouvé n'étaient pas très complet voir ne fonctionnaient pas...

    Voici les sources du programme "serveur" qui récupère les messages :

    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
     
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
     
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
     
    typedef struct T{
    	long mtype;
    	char mtext[1000];
    }Tampon;
     
    int main(int argc, char * argv[])
    {
    	//Création de la clef
    	key_t clef = ftok("/home/gautier/file", 'a');
     
    	//Demande d'accès à la file de message
    	int id = msgget(clef, 0666 | IPC_CREAT);
     
    	//En cas d'erreur
    	if(id == -1)
    	{
    		fprintf(stderr, "(%s) %d. Accès impossible à la file de message.\n", __FILE__, __LINE__);
    		exit(EXIT_FAILURE);
    	}
     
    	printf("clef : %d\n", id);
     
    	//Boucle principale
    	while(1)
    	{
    		Tampon message;
     
    		int rcv = msgrcv(id, (struct msgbuf *) &message, M_TMAX, 0L, 0);
     
    		printf("%d ok", rcv);
    	}
     
    	//Fin "propre"
    	return EXIT_SUCCESS;
    }
    Les sources du programme client, censé envoyé les messages

    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
     
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
     
    #include <sys/types.h>
    #include <sys/ipc.h>
    #include <sys/msg.h>
     
    typedef struct T{
    	long mtype;
    	char mtext[1000];
    }Tampon;
     
    int main(int argc, char * argv[])
    {
    	//Création de la clef
    	key_t clef = ftok("/home/gautier/file", 'b');
     
    	//Demande d'accès à la file de message
    	int id = msgget(clef, 0666);
     
    	//En cas d'erreur
    	if(id == -1)
    	{
    		fprintf(stderr, "(%s) %d. Accès impossible à la file de message.\n", __FILE__, __LINE__F);
    		exit(EXIT_FAILURE);
    	}
     
    	printf("clef : %d\n", id);
     
    	while (1) {
    		struct T msg;
    		int l, r;
     
    		printf("> ");
    		fgets(msg.mtext, M_TMAX, stdin);
    		l = strlen(msg.mtext);
    		msg.mtype = 1;
    		r = msgsnd(id, (struct msgbuf *) &msg, l + 1, 0);
    		if (r == -1)
    			perror("msgsnd");
    	}
     
    	//Fin "propre"
    	return EXIT_SUCCESS;
    }
    Le premier programme écrit le clef et attend indéfiniment.

    Le second se comporte sans erreur

    La commande "ipcs -a" lancé dans un troisième terminal montre bien la nouvelle file créée mais celle ci ne se remplit pas...

    Voilà donc je suis preneur de toute correction ou de tout exemple que vous pourriez me fournir, merci d'avance.

  2. #2
    Expert éminent sénior
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 690
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 690
    Points : 30 985
    Points
    30 985
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par gandalflemaia Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    		r = msgsnd(id, (struct msgbuf *) &msg, l + 1, 0);
    Salut

    Ton paramètre l+1 n'est pas bon. Une msq est comme une enveloppe et la taille en est toujours fixée. Elle doit correspondre à la taille du Tampon en y enlevant la taille du type (pourquoi cette aberration ? mystère).

    Accessoirement tu utilises mal ftok(). Le second paramètre doit être un nombre quelconque permettant de faire éventuellement une distinction entre différents programmes. Bon, ok, 'b' est un nombre mais je suis certain que c'était pas ton idée...

    Personnellement, j'utilise ftok(".", getuid()). Ca permet d'avoir une clef unique pour deux programmes
    - se trouvant dans le même dossier
    - appelés par le même user
    Assez pratique pour éviter les collisions de clef ipc dans un environnement multi-user...

    Concernant ton désespérant manque de tuto, tu en trouveras un sur mon site ici

    Et voici deux petits exemples correspondant à ce que tu veux faire
    Code c : 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
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    //                                                                            
    // SOURCE : msg_envoi.c                                                       
    //                                                                            
    // OBJET : msg_envoi                                                          
    //                                                                            
    // BUT : Envoyer des messages sur une boite aux lettres                       
    //                                                                            
    // PRINCIPE : Le premier argument est la clef de la boite (hexadécimal)       
    //            Le second (facultatif) est le type du message (decimal)         
    //            Les autres arguments sont les messages à envoyer                
    //                                                                            
    // USAGE : prog clef type [mess1 ...]                                         
    //	- Pas d'option                                                            
    //                                                                            
     
    #include <sys/types.h>						// Types prédéfinis "c"           
    #include <sys/mode.h>						// Modes et droits fichiers       
    #include <sys/ipc.h>						// Internal Process Comm.         
    #include <sys/msg.h>						// Boite aux lettres I.P.C.       
    #include <stdio.h>							// I/O fichiers classiques        
    #include <errno.h>							// Erreurs système                
     
    extern const char* const sys_errlist[];		// Liste messages erreurs         
     
    #define SZ_MESSAGE			(255)			// Taille max. message            
     
    typedef struct {
    	int no;									// No d'ordre                     
    	char txt[SZ_MESSAGE]; 					// Texte du message               
    }t_corps;		 							// Type "corps de message"        
     
    typedef struct {
    	mtyp_t mtype;							// Type de message                
    	t_corps mcorps; 						// Corps du message               
    }t_msgbuf;		 							// Type "message" au format "ipc" 
     
    // Fonction principale 
    main(
    	int argc, 								// Nbre arguments                 
    	char *argv[])							// Ptr arguments                  
    {
    	// Déclaration des variables 
    	int msg_id;								// Identifiant de la boite        
    	int status;								// Status de retour fonction      
    	int i;									// Indice de boucle               
    	key_t msg_key;							// Clef de la boite               
    	t_msgbuf msg_buf;						// Message à envoyer              
     
    	// Vérification au moins deux arguments 
    	if (argc <= 2)
    	{
    		fprintf(stderr, "Usage: %s clef type [mess1 ...]\n", argv[0]);
    		exit(errno);
    	}
     
    	// Conversion argument 1 (hexa) en nombre 
    	msg_key=strtoul(argv[1], NULL, 16);
     
    	// Récuperation argument 2 pour type 
    	msg_buf.mtype=atol(argv[2]);
    	if (msg_buf.mtype == 0)
    		msg_buf.mtype=1;					// Le type ne doit pas être à 0   
     
    	// Creation/Ouverture de la boite 
    	if ((msg_id=msgget(msg_key, IPC_CREAT|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) == (-1))
    	{
    		fprintf(stderr, "ligne %u - msgget(0x%08x) - %s\n", __LINE__, msg_key, sys_errlist[errno]);
    		exit(errno);
    	}
    	printf("Boite aux lettres 0x%x ouverte - valeur %d\n", msg_key, msg_id);
     
    	// Boucle sur le nombre d'arguments 
    	for (i=3; i < argc; i++)
    	{
    		// Le n° du message est son n° d'ordre dans la liste des arguments 
    		msg_buf.mcorps.no=i - 2;
     
    		// Le corps du message est l'argument "i" 
    		strcpy(msg_buf.mcorps.txt, argv[i]);
     
    		// Envoi du message 
    		if ((status=msgsnd(msg_id, &msg_buf, sizeof(t_corps), IPC_NOWAIT)) == (-1))
    		{
    			fprintf(stderr, "ligne %u - msgsnd(%d) - %s\n", __LINE__, msg_id, sys_errlist[errno]);
    			continue;
    		}
    		printf("\tmessage(type=%d) '%s'... envoyé - status %d\n", msg_buf.mtype, msg_buf.mcorps.txt, status);
    	}
    }

    Code c : 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
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    //                                                                            
    // SOURCE : msg_recup.c                                                       
    //                                                                            
    // OBJET : msg_recup                                                          
    //                                                                            
    // BUT : Récupérer les messages d'une boite aux lettres                       
    //                                                                            
    // PRINCIPE : Le premier argument est la clef de la boite (hexadecimal)       
    //            Si argument pas clef valide, il devient identifiant (décimal)   
    //            Le second (facultatif) est le type du message (decimal)         
    //            Le programme boucle sur le nombre initial de messages           
    //                                                                            
    // USAGE : prog clef/id type                                                  
    //	- Pas d'option                                                            
    //                                                                            
     
    #include <sys/types.h>						// Types prédéfinis "c"           
    #include <sys/ipc.h>						// Internal Process Comm.         
    #include <sys/msg.h>						// Boite aux lettres I.P.C.       
    #include <stdio.h>							// I/O fichiers classiques        
    #include <errno.h>							// Erreurs système                
     
    extern const char* const sys_errlist[];		// Liste messages erreurs         
     
    #define SZ_MESSAGE			(255)			// Taille max. message            
     
    typedef struct {
    	int no;									// No d'ordre                     
    	char txt[SZ_MESSAGE]; 					// Texte du message               
    }t_corps;		 							// Type "corps du message"        
     
    typedef struct {
    	mtyp_t mtype;							// Type de message                
    	t_corps mcorps; 						// Corps du message               
    }t_msgbuf;		 							// Type "message" au format "ipc" 
     
    // Fonction principale 
    main(
    	int argc, 								// Nbre arguments                 
    	char *argv[])							// Ptr arguments                  
    {
    	// Déclaration des variables 
    	unsigned short nb_msg;					// Nombre de messages présents    
    	int msg_id;								// Identifiant de la boite        
    	int status;								// Status de retour fonction      
    	mtyp_t msg_type;						// Type message demandé           
    	key_t msg_key;							// Clef de la boite               
    	t_msgbuf msg_buf;						// Message à récupérer            
    	struct msqid_ds info; 					// Information boite              
     
    	// Vérification au moins un argument 
    	if (argc <= 1)
    	{
    		fprintf(stderr, "Usage: %s clef/id [type]\n", argv[0]);
    		exit(errno);
    	}
     
    	// Conversion argument 1 (hexa) en nombre 
    	msg_key=strtoul(argv[1], NULL, 16);
     
    	// Récupération argument 2 (si existant) pour type 
    	msg_type=(argc > 2) ?atol(argv[2]) :0;
     
    	// Ouverture de la boite si clef valide 
    	if ((msg_id=msgget(msg_key, IPC_ALLOC)) == (-1))
    	{
    		fprintf(stderr, "ligne %u - msgget(0x%08x) - %s\n", __LINE__, msg_key, sys_errlist[errno]);
    		msg_id=strtoul(argv[1], NULL, 10);
    		printf("Clef 0x%08x invalide => Utilisation identifiant %d\n", msg_key, msg_id);
    	}
    	printf("Boite aux lettres 0x%x ouverte - valeur %d\n", msg_key, msg_id);
     
    	// Récuperation info boite 
    	if (msgctl(msg_id, IPC_STAT, &info) == (-1))
    	{
    		fprintf(stderr, "ligne %u - msgctl(%d) - %s\n", __LINE__, msg_id, sys_errlist[errno]);
    		exit(errno);
    	}
    	printf("Boite contient %hu messages (id=%d)\n", info.msg_qnum, msg_id); 
     
    	// Boucle sur le nombre de messages 
    	for (nb_msg=info.msg_qnum; nb_msg > 0; nb_msg--)
    	{
    		// Récupération du message 
    		status=msgrcv(msg_id, &msg_buf, sizeof(t_corps), msg_type, IPC_NOWAIT|MSG_NOERROR);
     
    		// Si récupération impossible mais pas par manque de place 
    		if (status == (-1))
    		{
    			// Si erreur n'est pas "plus de message" 
    			if (errno != ENOMSG)
    			{
    				fprintf(stderr, "ligne %u - msgrcv() - %s\n", __LINE__, sys_errlist[errno]);
    				exit(errno);
    			}
     
    			// On sort de la boucle 
    			break;
    		}
     
    		// Affichage chaine 
    		printf("\tmessage(type=%d): '%d %s' - status %d\n", msg_buf.mtype, msg_buf.mcorps.no, msg_buf.mcorps.txt, status);
    	}
     
    	// Fin du programme 
    	printf("Fin des messages de type %d (0x%x)\n", msg_type, msg_key);
    }
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    59
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 59
    Points : 124
    Points
    124
    Par défaut
    Ok, merci beaucoup. Je vais regarder ça de plus prêt! Mais effectivement, en modifiant le l+1 ça à l'air de déjà mieux marcher

Discussions similaires

  1. Réponses: 5
    Dernier message: 17/05/2007, 01h19
  2. [IPC] vider la file de messages
    Par waldoun dans le forum Linux
    Réponses: 4
    Dernier message: 14/05/2007, 19h43
  3. IPCS file de message
    Par jmjmjm dans le forum Linux
    Réponses: 5
    Dernier message: 25/01/2007, 13h36
  4. IPC - Files de messages - Structure des messages
    Par Mattius007 dans le forum C
    Réponses: 2
    Dernier message: 03/01/2007, 10h51
  5. IPC : Files de messages et accès exclusif
    Par thomasvst dans le forum C
    Réponses: 2
    Dernier message: 07/12/2005, 09h47

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