mq_receive: сообщение слишком длинное - PullRequest
9 голосов
/ 11 апреля 2011

Я осуществляю связь между двумя процессами, используя очередь.Проблема в том, что когда я вызываю функцию mq_receive, я получаю эту ошибку: Сообщение слишком длинное.

Я сделал следующее:

struct mq_attr attr;

long size = attr.mq_msgsize;
.... // initializing the queue "/gateway"

int rc = mq_receive(gateway, buffer, size, &prio);

Если я распечатываю значение размера, я получаюsize = 1, а когда я печатаю тот же размер, но из другой программы (полученной по тому же механизму), я получаю что-то не длинное целое (-1217186280) ...

Как я могу решить эту ошибку ?.... так что, хотя size = 1, я считаю правильным сказать «сообщение слишком длинное», но почему 1?

PS Я также пытался поставить:

int rc = mq_receive(gateway, buffer, sizeof(buffer), &prio);

, но без результата.

Ответы [ 4 ]

20 голосов
/ 26 октября 2011

Похоже, вам нужно более внимательно читать документы. Когда вы звоните mq_receive, вы должны передать размер буфера назначения. Этот размер должен быть больше, чем атрибут mq_msgsize очереди . Кроме того, похоже, что у вас есть ошибка при инициализации атрибутов очереди, которая делает невозможным правильный вызов mq_receive. Вот стандартный сеанс очереди сообщений:

  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. Создать очередь с mq_open в главном процессе ( doc ):

    mqd_t queue = mq_open(qname, O_CREAT|O_RDWR, 0644, &attr);
    
  3. В процессе записи открытая очередь для записи:

    mqd_t queue = mq_open(qname, O_WRONLY);
    

    И отправьте текст. Длина текста должна быть меньше mq_msgsize атрибута очереди ( doc ):

    mq_send(queue, "some message", strlen("some message")+1, 1);
    
  4. В процессе чтения откройте очередь для чтения:

    mqd_t queue = mq_open(qname, O_RDONLY);
    

    А затем выделить буфер и получить сообщение. Размер буфера * должен быть больше атрибута mq_msgsize очереди. Здесь мы создаем 50-байтовый буфер, в то время как mq_msgsize == 33 ( doc ):

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

Также помните, что вы должны использовать %ld для печати long вместо %d.

7 голосов
/ 21 октября 2011

При отладке очередей POSIX в реальном времени вы должны начать с примера программы, которая работает, и идти дальше оттуда.После запуска примера программы необходимо убедиться, что ваш собственный код выполняет все шаги.

Следующая программа была успешно протестирована в 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;
}

Вывод в моей системе:

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.
5 голосов
/ 15 января 2014

Не забудьте отсоединить очередь сообщений перед повторным запуском вашей программы. Если вы не отсоедините его, он все равно будет использовать старые настройки очереди сообщений. Это происходит, когда вы заканчиваете свою программу с помощью Ctrl + C. Я думаю, что это хорошая идея, чтобы поместить следующий код в начале программы:

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

Альтернативная форма (стиль C ++), которая проверяет наличие реальных ошибок (например, разрешений) и игнорирует случаи, когда очередь уже существует или нет:

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 голосов
/ 02 апреля 2019

Просто поправка выше ... "Этот размер должен быть равен или больше , чем атрибут mq_msgsize очереди"

Вероятно, требуется равный размер, если вы вместо этого передаете структурубуфера: см .: отправить структуру в mq_send

...