【问题标题】:mq_receive Message too long - no message sentmq_receive 消息太长 - 没有消息发送
【发布时间】:2017-04-20 12:54:00
【问题描述】:

我正在第一次练习消息队列。我希望 mq_receive 阻止,所以我没有打开 O_NOBLOCK。

mq_receive 方法正在返回,perror() 正在打印“消息太长”。这是在我发送消息之前。

ATM 发送消息:

void* run_ATM(void* arg) {
    int status;

    char accountNumber[15];
    cout << "ATM is running" << endl;
    cout << "Please input an account number > ";
    cin >> accountNumber;
    status = mq_send(PIN_MSG, accountNumber, sizeof(accountNumber), 1);

}

数据库接收它们

void* run_DB(void* arg){
    cout << "Database server running" << endl;
    int status;
    char received_acct_number[30];

    while(1){
        status = mq_receive(PIN_MSG, received_acct_number, 100, NULL);
        if (status < 0){
            perror("error ");
        } else {
            cout << "received account number\t" << received_acct_number << endl;
        }
    }
}

这只是初步的代码 - 所以它最终会做更多的事情。我只是想获得一个基本的工作示例。

编辑:运行它所需的其他代码:

#define PIN_MSG_NAME "/pin_msg"
#define DB_MSG_NAME "/db_msg"

#define MESSAGE_QUEUE_SIZE 15

pthread_t ATM;
pthread_t DB_server;
pthread_t DB_editor;
void* run_ATM(void* arg);
void* run_DB(void* arg);

static struct mq_attr mq_attribute;
static mqd_t PIN_MSG, DB_MSG;

int main(int argc, char const *argv[])
{
    pthread_attr_t attr;


    mq_attribute.mq_maxmsg = 10; //mazimum of 10 messages in the queue at the same time
    mq_attribute.mq_msgsize = MESSAGE_QUEUE_SIZE;

    PIN_MSG = mq_open(PIN_MSG_NAME, O_CREAT | O_RDWR, 0666, &mq_attribute);
    DB_MSG = mq_open(DB_MSG_NAME, O_CREAT | O_RDWR, 0666, &mq_attribute);

    pthread_attr_init(&attr);
    pthread_attr_setstacksize(&attr, 1024*1024);

    long start_arg = 0; //the start argument is unused right now
    pthread_create(&ATM, NULL, run_ATM, (void*) start_arg);
    pthread_create(&DB_server, NULL, run_DB, (void*) start_arg);

    pthread_join(ATM, NULL);
    pthread_join(DB_server, NULL);
}

接收缓冲区大于消息队列大小,应该没有问题吧?

【问题讨论】:

  • 你能给我们足够的代码来复制这个问题吗?例如,MESSAGE_QUEUE_SIZE 是什么? PIN_MSG 是什么?

标签: c++ message-queue


【解决方案1】:

如果你检查函数返回的错误并打印出来,错误就会很明显。您正在将accountNumberPIN 转换为指针,而不是转换它们的地址。你想要:

status = mq_send(PIN_MSG, (const char*) &accountNumber, MESSAGE_QUEUE_SIZE, 1);

status = mq_send(PIN_MSG, (const char*) &PIN, MESSAGE_QUEUE_SIZE, 1);

status = mq_receive(PIN_MSG, (char*) &received_acct_number, 100, NULL);

status = mq_receive(PIN_MSG, (char*) &received_PIN, MESSAGE_QUEUE_SIZE, NULL);

请注意,我们的代码仍然存在很多问题,最明显的是您因未正确处理这些变量的大小而超出了这些变量的范围。您可以像这样修复它:

status = mq_send(PIN_MSG, (const char*) &accountNumber, sizeof (accountNumber), 1);

status = mq_send(PIN_MSG, (const char*) &PIN, sizeof (PIN), 1);

status = mq_receive(PIN_MSG, (char*) &received_acct_number, sizeof(received_acct_number), NULL);

status = mq_receive(PIN_MSG, (char*) &received_PIN, sizeof(received_PIN), NULL);

但实际上,您应该有某种消息格式,并且应该将消息序列化到该格式或从该格式序列化。

【讨论】:

  • 创建消息格式是什么意思?我应该把数字封装在什么东西里吗?
  • @BrydonGibson 我的意思是,如果你要发送消息,你应该有一些文档格式来解释它们是如何发送的。例如,如果格式是每条消息是 100 字节,你不需要一个 100 字节的缓冲区来接收它们吗?或者这些消息应该有多大?
  • 将大小更改为 sizeof(thingBeingSent) 可防止 mq_receive 阻塞。它返回 -1 和 perror() 打印 Message too long
  • @BrydonGibson 你能显示正在使用的确切代码行吗?
【解决方案2】:

所以看起来主要问题在于剩余的消息队列,因为它们在代码中没有正确关闭/取消链接。

我的原始代码中存在一些错误,我感谢指出这一点并为我提供解决方案的答案。

尝试更改消息格式时出现问题,我猜当再次调用mq_open 时,它不会更改消息大小(因为消息队列已经存在)。这会导致代码中的大小错误。重启是一种解决方法,但解决方案是使用mq_unlink() 正确清理,然后使用mq_close()

【讨论】:

    猜你喜欢
    • 2011-08-03
    • 2017-11-23
    • 2020-07-19
    • 1970-01-01
    • 1970-01-01
    • 2013-09-04
    • 1970-01-01
    • 2018-07-03
    • 1970-01-01
    相关资源
    最近更新 更多