2016-08-18 126 views
2

我在Linux中使用IPC的消息队列(类似于this后)编写了一个简单的C程序。为了简单起见,在相同的过程中调用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如何获得发送缓冲区的确切大小?我应该分别发送缓冲区大小吗?

回答

2

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

只要邮件大小不超过队列的mq_msgsize属性时,传递给mq_send大小由mq_received返回不变。

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

#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属性。如果你这样做,你需要设计一些协议,告诉接收方需要多少条消息以及如何组合它们。长度不一定是必需的,但将它与消息的数量一起发送以简化接收端的分配会更方便。

+0

@ManiAm:这个答案符合你的需求吗?您还有其它问题么? – chqrlie

+0

感谢您的回答。我同意发送字符串时,不需要发送大小。但是在一个通用缓冲区(由uint8_t组成)中,mq_receive如何知道缓冲区的大小是多少? – ManiAm

+1

@ManiAm:'mq_send'将消息长度存储在消息队列结构中,'mq_receive'从那里获取消息长度。发送一个字符串并不重要,'mq_send'不会对消息的内容做任何假设,对于任何类型的内容(无论是“char”,“uint8_t”还是其他任何内容)都是如此。你甚至可以传递一个结构的地址,只要它不包含任何指针,因为指针值对接收端来说是没有意义的。 – chqrlie

相关问题