Search code examples
cipcmessage-queuemessage-type

IPC MSG Queue how to identify message type of each message that is sent?


I just learned about MSG queues and I tried to write two processes with common keys, where one sends messages and another reads messages then removes the queue. But the problem is, I want to know which message had which type when they're sent.

Here is my console results:

MSG sent: MSG_6 MSG sent: MSG_2 MSG sent: MSG_8 MSG sent: MSG_9 MSG sent: MSG_8 MSG sent: MSG_3 MSG sent: MSG_6 MSG sent: MSG_6 MSG sent: MSG_2 MSG sent: MSG_5 Recieved type: 5, MSG_6 Recieved type: 5, MSG_2 Recieved type: 5, MSG_8 Recieved type: 5, MSG_9 Recieved type: 5, MSG_8 Recieved type: 5, MSG_3 Recieved type: 5, MSG_6 Recieved type: 5, MSG_6 Recieved type: 5, MSG_2 Recieved type: 5, MSG_5 Now removing the QEUE in 3 seconds

I was expecting that mtype would be same as each MSG sent. However, as you can see receiver process only prints very last MSG type. If I'm able to get each MSG types so that I can sort them in a some way.

IPC_COMMON.h where both sender and receiver includes this header file.

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>

#define TEST_ERROR    if (errno) {fprintf(stderr, \
                      "%s:%d: PID=%5d: Error %d (%s)\n", \
                      __FILE__,         \
                      __LINE__,         \
                      getpid(),         \
                      errno,            \
                      strerror(errno));}
#define MSG_LEN 120

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

#define MY_KEY 0x123456
#define MSGTYPE_RM  7

SENDER.c

#include "testCommon.h"
#include <time.h>

int main() {
    int id_q;
    struct msgbuf my_msg;
    int typeArr[10];
    int i;
    
    id_q = msgget(MY_KEY, IPC_CREAT | 0600);
    TEST_ERROR;
    
    srand(time(NULL));
        
    for(i = 0; i < 10; i++) {
        typeArr[i] = rand() % 10;
        my_msg.mtype = typeArr[i];
        printf("Printing types %d\n", typeArr[i]);      
    }
    
    for(i = 0; i < 10; i++) {
        switch(typeArr[i]) {
        case 0:
            strcpy(my_msg.mtext , "MSG_0");
            msgsnd(id_q, &my_msg, MSG_LEN, 0);
            printf("MSG sent: %s\n", my_msg.mtext);
            break;
        case 1:
            strcpy(my_msg.mtext , "MSG_1");
            msgsnd(id_q, &my_msg, MSG_LEN, 0);
            printf("MSG sent: %s\n", my_msg.mtext);
            break;
        case 2:
            strcpy(my_msg.mtext , "MSG_2");
            msgsnd(id_q, &my_msg, MSG_LEN, 0);
            printf("MSG sent: %s\n", my_msg.mtext);
            break;
        case 3:
            strcpy(my_msg.mtext , "MSG_3");
            msgsnd(id_q, &my_msg, MSG_LEN, 0);
            printf("MSG sent: %s\n", my_msg.mtext);
            break;
        case 4:
            strcpy(my_msg.mtext , "MSG_4");
            msgsnd(id_q, &my_msg, MSG_LEN, 0);
            printf("MSG sent: %s\n", my_msg.mtext);
            break;
        case 5:
            strcpy(my_msg.mtext , "MSG_5");
            msgsnd(id_q, &my_msg, MSG_LEN, 0);
            printf("MSG sent: %s\n", my_msg.mtext);
            break;
        case 6:
            strcpy(my_msg.mtext , "MSG_6");
            msgsnd(id_q, &my_msg, MSG_LEN, 0);
            printf("MSG sent: %s\n", my_msg.mtext);
            break;
        case 7:
            strcpy(my_msg.mtext , "MSG_7");
            msgsnd(id_q, &my_msg, MSG_LEN, 0);
            printf("MSG sent: %s\n", my_msg.mtext);
            break;
        case 8:
            strcpy(my_msg.mtext , "MSG_8");
            msgsnd(id_q, &my_msg, MSG_LEN, 0);
            printf("MSG sent: %s\n", my_msg.mtext);
            break;
        case 9:
            strcpy(my_msg.mtext , "MSG_9");
            msgsnd(id_q, &my_msg, MSG_LEN, 0);
            printf("MSG sent: %s\n", my_msg.mtext);
            break;
        default:
            fprintf(stderr, "Error occurred\n.");
            TEST_ERROR;
        }
    }
    return 0;
}

RECEIVER.c

#include "testCommon.h"

int main() {
    int q_id, num_bytes, i;
    struct msgbuf my_msg;
    num_bytes = 0;
    q_id = msgget(MY_KEY, IPC_CREAT | 0600);
    TEST_ERROR;
    
    while (1) {
        /* now receiving the message */
            for(i = 0; i < 10; i++) {
            num_bytes += msgrcv(q_id, &my_msg, MSG_LEN, 0, 0);
            printf("Recieved type: %ld, %s \n", my_msg.mtype, my_msg.mtext);
            }   
            if(num_bytes >= 0)
            break;  
    }
    printf("Now removing the QEUE in 3 seconds\n");
    sleep(3);
    msgctl(q_id, IPC_RMID, NULL);       
}
    


Solution

  • I was expecting that mtype would be same as each MSG sent.

    There are a few issues with your code, which I have mostly raised in comments on the question. But the main issue appears to be that you set my_msg.mtype for the last time before you send any messages to the queue. You set the mtext data each time, but not mtype. I would expect, then, that all the messages come across with the message type designated in the sender by typeArr[9], as that's the last mtype value you set.

    You might try this instead of the sender's two for loops:

        for (i = 0; i < 10; i++) {
            my_msg.mtype = 1 + rand() % 9;
            sprintf(my_msg.mtext, "MSG_%ld", my_msg.mtype);
            ssize_t result = msgsnd(id_q, &my_msg, MSG_LEN, 0);
            if (result == -1) {
                // handle error ...
            } else {
                printf("MSG type %ld sent: %s\n", my_msg.mtype, my_msg.mtext);
            }
        }