在消息队列上发送可变大小的缓冲区

时间:2016-08-18 08:43:56

标签: c linux

我在Linux中编写了一个简单的C程序,它使用IPC的消息队列(类似于this post)。为简单起见,mq_sendmq_receive在同一过程中被调用。

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

#define QUEUE_NAME  "/test_queue2"

int main(int argc, char **argv)
{
    /* initialize the queue attributes */
    struct mq_attr attr;
    attr.mq_flags = 0;
    attr.mq_maxmsg = 10;
    attr.mq_msgsize = 30;
    attr.mq_curmsgs = 0;

    /* create the message queue */
    mqd_t mq = mq_open(QUEUE_NAME, O_CREAT | O_WRONLY, 0644, &attr);
    if (mq < 0) {
        printf("error in mq_open 1");
        exit(1);
    }

    /* send the message */
    int rc = mq_send(mq, "mani123", 8, 0); // need to include the null character too!
    if (rc < 0) {
        printf("error in mq_send");
        exit(1);
    }

    // ---------------------------------------------------------------

    mqd_t mq2 = mq_open(QUEUE_NAME, O_RDONLY);
    if (mq2 < 0) {
        printf("error in mq_open 2: %s", strerror(errno));
        exit(1);
    }

    char rcvmsg[50];
    rc = mq_receive(mq2, rcvmsg, 50, 0);
    if (rc < 0) {
        printf("error in mq_receive");
        exit(1);
    }

    printf("%s", rcvmsg);

    return 0;
}

我正在使用消息队列发送/接收常量字符串。现在我想重复一遍通用缓冲区(char数组)。我使用mq_send发送缓冲区内容,但我的问题是mq_receive如何获得发送缓冲区的确切大小?我应该单独发送缓冲区大小吗?

1 个答案:

答案 0 :(得分:2)

快速回答是不,您不需要单独发送邮件大小。

只要邮件大小不超过队列的mq_msgsize属性,传递给mq_send的大小就会由mq_received保持不变。

您不需要发送'\0'终结符,但是您不需要发送它,它也不会被接收,并且接收代码必须设置它以确保接收的字符串为空终止。在这种情况下要小心,在目标缓冲区的末尾允许一个额外的字节:

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

#define QUEUE_NAME  "/test_queue2"

int main(int argc, char **argv) {
    /* initialize the queue attributes */
    struct mq_attr attr;
    attr.mq_flags = 0;
    attr.mq_maxmsg = 10;
    attr.mq_msgsize = 30;
    attr.mq_curmsgs = 0;

    /* create the message queue */
    mqd_t mq = mq_open(QUEUE_NAME, O_CREAT | O_WRONLY, 0644, &attr);
    if (mq < 0) {
        printf("error in mq_open 1: %s\n", strerror(errno));
        exit(1);
    }

    /* send the message */
    const char *str = "mani123";
    int rc = mq_send(mq, str, strlen(str), 0); // no need to include the null character
    if (rc < 0) {
        printf("error in mq_send: %s\n", strerror(errno));
        exit(1);
    }

    // ---------------------------------------------------------------

    mqd_t mq2 = mq_open(QUEUE_NAME, O_RDONLY);
    if (mq2 < 0) {
        printf("error in mq_open 2: %s\n", strerror(errno));
        exit(1);
    }

    char rcvmsg[50 + 1];  // 50 is more than enough since attr.mq_msgsize = 30 
    rc = mq_receive(mq2, rcvmsg, 50, 0);
    if (rc < 0) {
        printf("error in mq_receive 2: %s\n", strerror(errno));
        exit(1);
    }
    rcvmsg[rc] = '\0';

    printf("received: %s\n", rcvmsg);

    return 0;
}

对于长答案,您需要考虑是否要发送长于最大消息队列mq_msgsize属性的二进制消息。如果你这样做,你需要设计某种协议,告诉接收方预期有多少消息以及如何组合它们。长度不一定是必需的,但将它与消息数一起发送以简化接收方的分配会更方便。