2010-06-16 13 views

Respuesta

56

El siguiente es un ejemplo simple de un servidor que recibe mensajes de clientes hasta que recibe un mensaje de "salida" que indica que se detenga.

El código para el servidor :

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <sys/stat.h> 
#include <sys/types.h> 
#include <errno.h> 
#include <mqueue.h> 

#include "common.h" 

int main(int argc, char **argv) 
{ 
    mqd_t mq; 
    struct mq_attr attr; 
    char buffer[MAX_SIZE + 1]; 
    int must_stop = 0; 

    /* initialize the queue attributes */ 
    attr.mq_flags = 0; 
    attr.mq_maxmsg = 10; 
    attr.mq_msgsize = MAX_SIZE; 
    attr.mq_curmsgs = 0; 

    /* create the message queue */ 
    mq = mq_open(QUEUE_NAME, O_CREAT | O_RDONLY, 0644, &attr); 
    CHECK((mqd_t)-1 != mq); 

    do { 
     ssize_t bytes_read; 

     /* receive the message */ 
     bytes_read = mq_receive(mq, buffer, MAX_SIZE, NULL); 
     CHECK(bytes_read >= 0); 

     buffer[bytes_read] = '\0'; 
     if (! strncmp(buffer, MSG_STOP, strlen(MSG_STOP))) 
     { 
      must_stop = 1; 
     } 
     else 
     { 
      printf("Received: %s\n", buffer); 
     } 
    } while (!must_stop); 

    /* cleanup */ 
    CHECK((mqd_t)-1 != mq_close(mq)); 
    CHECK((mqd_t)-1 != mq_unlink(QUEUE_NAME)); 

    return 0; 
} 

El código para el cliente :

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <sys/stat.h> 
#include <sys/types.h> 
#include <mqueue.h> 

#include "common.h" 


int main(int argc, char **argv) 
{ 
    mqd_t mq; 
    char buffer[MAX_SIZE]; 

    /* open the mail queue */ 
    mq = mq_open(QUEUE_NAME, O_WRONLY); 
    CHECK((mqd_t)-1 != mq); 


    printf("Send to server (enter \"exit\" to stop it):\n"); 

    do { 
     printf("> "); 
     fflush(stdout); 

     memset(buffer, 0, MAX_SIZE); 
     fgets(buffer, MAX_SIZE, stdin); 

     /* send the message */ 
     CHECK(0 <= mq_send(mq, buffer, MAX_SIZE, 0)); 

    } while (strncmp(buffer, MSG_STOP, strlen(MSG_STOP))); 

    /* cleanup */ 
    CHECK((mqd_t)-1 != mq_close(mq)); 

    return 0; 
} 

La cabecera común:

#ifndef COMMON_H_ 
#define COMMON_H_ 

#define QUEUE_NAME "/test_queue" 
#define MAX_SIZE 1024 
#define MSG_STOP "exit" 

#define CHECK(x) \ 
    do { \ 
     if (!(x)) { \ 
      fprintf(stderr, "%s:%d: ", __func__, __LINE__); \ 
      perror(#x); \ 
      exit(-1); \ 
     } \ 
    } while (0) \ 


#endif /* #ifndef COMMON_H_ */ 

Compilación:

gcc -o server server.c -lrt 
gcc -o client client.c -lrt 
+1

Una breve observación. Su código para el cliente falta lo siguiente incluye para hacerlo compilar: '#include #include #include ' – MKroehnert

+0

Ejemplo muy detallado! +++ 1 gracias !! – Viet

+2

Dulce, me encanta tu macro CHECK. – g33kz0r

1
#include <stdio.h> 
#include <fcntl.h> 
#include <mqueue.h> 

int main(int argc, char *argv[]) 
{ 
    mqd_t mq;    // message queue 
    struct mq_attr ma;  // message queue attributes 
    int status = 0; 
    int a = 5; 
    int b = 0; 

    printf("a = %d, b = %d\n", a, b); 

    // Specify message queue attributes. 
    ma.mq_flags = 0;    // blocking read/write 
    ma.mq_maxmsg = 16;    // maximum number of messages allowed in queue 
    ma.mq_msgsize = sizeof(int); // messages are contents of an int 
    ma.mq_curmsgs = 0;    // number of messages currently in queue 

    // Create the message queue with some default settings. 
    mq = mq_open("/test_queue", O_RDWR | O_CREAT, 0700, &ma); 

    // -1 indicates an error. 
    if (mq == -1) 
    { 
     printf("Failed to create queue.\n"); 
     status = 1; 
    } 

    if (status == 0) 
    { 
     status = mq_send(mq, (char *)(&a), sizeof(int), 1); 
    } 

    if (status == 0) 
    { 
     status = mq_receive(mq, (char *)(&b), sizeof(int), NULL); 
    } 

    if ((status == 0) && (mq_close(mq) == -1)) 
    { 
     printf("Error closing message queue.\n"); 
     status = 1; 
    } 

    if ((status == 0) && (mq_unlink("test_queue") == -1)) 
    { 
     printf("Error deleting message queue.\n"); 
     status = 1; 
    } 

    printf("a = %d, b = %d\n", a, b); 

    return status; 
} 
+2

Hay algo muy malo con su implementación. Es una idea terrible pasar punteros a través de mqueues, ya que un puntero solo es válido en su propio proceso, mientras que las mqueues están destinadas a ser usadas entre procesos. Pero al final estás pasando ints. Puede funcionar solo porque sizeof (void *)> sizeof (int) en la mayoría de las arquitecturas. – Juliano

+0

@Juliano: Gracias, estaba usando sizeof (void *) donde debería haber sido sizeof (int). Este es solo un ejemplo sintético para mostrar el uso de mqueue. Demuestra el contenido de un entero que se mueve a través de la cola en otro entero donde ambos se tratan como búferes. –

+0

@Armardeep: sizeof (a) y sizeof (b) serían mejores que sizeof (int). – camh

0

mq_send(mq, (char *)(&a), sizeof(int), 1) copias sizeof(int) bytes de memoria intermedia &a en este caso, que no lleva el puntero de la variable a, pero lleva el valor de la variable a de un proceso a otro proceso. La implementación es correcta.

0

Código como abajo para su referencia:

IPC_msgq_rcv.c

#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/msg.h> 
#include <stdio.h> 
#include <stdlib.h> 
#define MAXSIZE  128 

void die(char *s) 
{ 
    perror(s); 
    exit(1); 
} 

struct msgbuf 
{ 
    long mtype; 
    char mtext[MAXSIZE]; 
}; 


void main() 
{ 
    int msqid; 
    key_t key; 
    struct msgbuf rcvbuffer; 

    key = 1234; 

    if ((msqid = msgget(key, 0666)) < 0) 
     die("msgget()"); 


    //Receive an answer of message type 1. 
    if (msgrcv(msqid, &rcvbuffer, MAXSIZE, 1, 0) < 0) 
     die("msgrcv"); 

    printf("%s\n", rcvbuffer.mtext); 
    exit(0); 
} 

IPC_msgq_send.c

#include <sys/types.h> 
#include <sys/ipc.h> 
#include <sys/msg.h> 
#include <stdio.h> 
#include <string.h> 
#include <stdlib.h> 
#define MAXSIZE  128 

void die(char *s) 
{ 
    perror(s); 
    exit(1); 
} 

struct msgbuf 
{ 
    long mtype; 
    char mtext[MAXSIZE]; 
}; 

main() 
{ 
    int msqid; 
    int msgflg = IPC_CREAT | 0666; 
    key_t key; 
    struct msgbuf sbuf; 
    size_t buflen; 

    key = 1234; 

    if ((msqid = msgget(key, msgflg)) < 0) //Get the message queue ID for the given key 
     die("msgget"); 

    //Message Type 
    sbuf.mtype = 1; 

    printf("Enter a message to add to message queue : "); 
    scanf("%[^\n]",sbuf.mtext); 
    getchar(); 

    buflen = strlen(sbuf.mtext) + 1 ; 

    if (msgsnd(msqid, &sbuf, buflen, IPC_NOWAIT) < 0) 
    { 
     printf ("%d, %ld, %s, %d \n", msqid, sbuf.mtype, sbuf.mtext, (int)buflen); 
     die("msgsnd"); 
    } 

    else 
     printf("Message Sent\n"); 

    exit(0); 
} 

Compilar cada una de la fuente archivos, para obtener un escritor-ejecutable y lector-ejecutable. Como continuación ::

gcc -o MQsender IPC_msgq_send.c

gcc -o MQreceiver IPC_msgq_rcv.c

La ejecución de cada uno de los binarios, puede enviar el mensaje y leer el mensaje de la cola de mensajes.Además, trate de ver el estado de la cola de mensajes, por orden de marcha (en diferentes estados de la cola):

ipcs -Q

Para el sistema Linux, se puede saber todos los detalles de la CIP los mecanismos y las colas disponibles, etc, mediante el uso de:

ipcs -a

Reference Blog

Cuestiones relacionadas