mq_receive: message too long

前端 未结 4 940
再見小時候
再見小時候 2020-12-31 11:20

I am implementing a communication between 2 processes using a queue. The problem is that when I call the function mq_receive, I get this error: Message too long.

I h

相关标签:
4条回答
  • 2020-12-31 11:31

    It seems like you need to read the docs more carefully. When you call mq_receive you should pass size of the destination buffer. This size must be greater than the mq_msgsize attribute of the queue. In addition, it seems like you have an error in queue attributes initialisation that makes proper mq_receive call impossible. Here is standard message queue session:

    1. Fill mq_attr struct (doc):

      struct mq_attr attr;  
      attr.mq_flags = 0;  
      attr.mq_maxmsg = 10;  
      attr.mq_msgsize = 33;  
      attr.mq_curmsgs = 0;  
      
    2. Create queue with mq_open in master process (doc):

      mqd_t queue = mq_open(qname, O_CREAT|O_RDWR, 0644, &attr);
      
    3. In writer process open queue for writing:

      mqd_t queue = mq_open(qname, O_WRONLY);
      

      And send some text. Length of the text must be lesser than mq_msgsize attribute of the queue (doc):

      mq_send(queue, "some message", strlen("some message")+1, 1);
      
    4. In reader process open queue for reading:

      mqd_t queue = mq_open(qname, O_RDONLY);
      

      And then allocate buffer and receive message. Size of buffer *must be greater than the mq_msgsize attribute of the queue. Here we create 50-byte buffer while mq_msgsize == 33 (doc):

      char rcvmsg[50];
      int iret = mq_receive(queue, rcvmsg, 50, NULL);
      

    Also remember that you should use %ld for print long instead of %d.

    0 讨论(0)
  • 2020-12-31 11:40

    When debugging realtime POSIX queues, you should start with a sample program which works and go forward from there. Once you have the sample program running, it should be a simple matter of ensuring that your own code follows all the steps.

    The following program has been tested successfully under Ubuntu 11.04:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    #include <mqueue.h>
    
    #define MQNAME "/pax"
    #define MQMESG "Hello there!"
    
    static mqd_t serverUp (void) {
        int rc;
        mqd_t svrHndl;
        struct mq_attr mqAttr;
    
        printf ("Bringing up server.\n");
        rc = mq_unlink (MQNAME);
        if (rc < 0) {
            printf ("   Warning %d (%s) on server mq_unlink.\n",
                errno, strerror (errno));
        }
    
        mqAttr.mq_maxmsg = 10;
        mqAttr.mq_msgsize = 1024;
        svrHndl = mq_open (MQNAME, O_RDWR|O_CREAT, S_IWUSR|S_IRUSR, &mqAttr);
        if (svrHndl < 0) {
            printf ("   Error %d (%s) on server mq_open.\n",
                errno, strerror (errno));
            exit (1);
        }
        printf ("   Server opened mqd_t of %d.\n", svrHndl);
        return svrHndl;
    }
    
    static void serverReceive (mqd_t svrHndl) {
        int rc;
        char buffer[2048];
        printf ("Server receiving on mqd_t %d.\n", svrHndl);
        rc = mq_receive (svrHndl, buffer, sizeof (buffer), NULL);
        if (rc < 0) {
            printf ("   Error %d (%s) on server mq_receive.\n",
                errno, strerror (errno));
            exit (1);
        }
        printf ("   Received [%s].\n", buffer);
    }
    
    static void serverDown (mqd_t svrHndl) {
        printf ("Bringing down server with mqd_t %d.\n", svrHndl);
        mq_close (svrHndl);
    }
    static void clientSend (void) {
        mqd_t cliHndl;
        int rc;
        printf ("Client sending.\n");
        cliHndl = mq_open (MQNAME, O_RDWR);
        if (cliHndl < 0) {
            printf ("   Error %d (%s) on client mq_open.\n",
                errno, strerror (errno));
            exit (1);
        }
        printf ("   Client opened mqd_t of %d.\n", cliHndl);
    
        rc = mq_send (cliHndl, MQMESG, sizeof (MQMESG), 1);
        if (rc < 0) {
            printf ("   Error %d (%s) on client mq_send.\n",
                errno, strerror (errno));
            exit (1);
        }
    
        mq_close (cliHndl);
    }
    
    int main (void) {
        mqd_t svrHndl;
    
        svrHndl = serverUp ();
        clientSend ();
        serverReceive (svrHndl);
        serverDown (svrHndl);
    
        return 0;
    }
    

    The output on my system is:

    Bringing up server.
       Server opened mqd_t of 3.
    Client sending.
       Client opened mqd_t of 4.
    Server receiving on mqd_t 3.
       Received [Hello there!].
    Bringing down server with mqd_t 3.
    
    0 讨论(0)
  • 2020-12-31 11:44

    Just a correction above... "This size must be equal or greater than the mq_msgsize attribute of the queue"

    Equal size is probably required if you are passing a struct instead of a buffer: see: send struct in mq_send

    0 讨论(0)
  • 2020-12-31 11:46

    Don't forget to unlink the message queue before running your program again. If you dont unlink it, it will still use the old message queue settings. This happens when you end your program with Ctrl+C. I think it is a good idea to put the following code at the beginning of the program:

    if(mq_unlink(QUEUENAME) == 0)
      fprintf(stdout, "Message queue %s removed from system.\n", QUEUENAME);
    

    An alternative form (C++ style) that checks for real errors (like permissions) and ignores the cases where the queue already exists or not:

    int rc = mq_unlink(name.c_str());
    if (rc != 0 && errno != ENOENT)
          THROW_ERRNO_EXCEPTION();  
    
    // ENOENT is the status code if the queue doesn't exist, which is not an error
    // if you are immediately going to create it.
    
    0 讨论(0)
提交回复
热议问题