gpt4 book ai didi

c++ - 如何从消息队列接收动态长度数据?

转载 作者:行者123 更新时间:2023-11-30 00:42:23 24 4
gpt4 key购买 nike

我必须使用 SysV 消息队列为大学项目发送和接收动态数据。

数据的长度在单独的消息中传输,size因此是已知的。

这就是我尝试接收数据的方式。我必须承认我不是 C++ 专家,尤其是在内存分配方面。

<罢工>

<罢工>
struct {
long mtype;
char *mdata;
} msg;

msg.mdata = (char *)malloc(size * sizeof(char));

msgrcv(MSGQ_ID, &msg, size, MSG_ID, 0);

问题好像是 malloc打电话,但我不知道该怎么做。

编辑

我尝试的是在消息队列周围的 OO 包装器中使用某种读取 方法。我想将消息队列中的数据读入 char[]std::string .我现在所拥有的(简化)如下所示。

bool Wrapper::read(char *data, int length)
{
struct Message {
long mtype;
std::string mdata;
};

Message msg;
msg.mdata = std::string(size, '\0');

if(msgrcv(MSGQ_ID, &msg, size, MSG_ID, 0) < 0)
{
return false;
}

memcpy(data, msg.mdata.c_str(), msg.mdata.size());

return true;
}

我得到的只是段错误或完全损坏的数据(尽管这些数据有时包含我想要的内容)。

最佳答案

您不能将指向包含 std::string 成员的结构的指针传递给 msgrcv,这违反了接口(interface)协定。

传递给 msgrcv 的第二个参数需要指向一个缓冲区,该缓冲区具有足够的空间来存储 struct { long mtype; 形式的“普通”C 结构;字符 mdata[大小]; }; 其中 size 是 msgrcv 的第三个参数。

不幸的是,由于可能的对齐问题,确定此缓冲区的大小可能取决于 size,但您必须假设它不在提供此类接口(interface)的系统上。您可以使用标准的 offsetof 宏来帮助确定此大小。

由于 vector 连续存储其组件,一旦知道缓冲区的大小,就可以调整 charvector 的大小并使用这个用来保存缓冲区。使用 vector 可以免除您手动释放删除[]缓冲区的义务。

你需要做这样的事情。

std::string RecvMessage()
{
extern size_t size; // maximum size, should be a parameter??
extern int MSGQ_ID; // message queue id, should be a parameter??
extern long MSG_ID; // message type, should be a parameter??

// ugly struct hack required by msgrcv
struct RawMessage {
long mtype;
char mdata[1];
};

size_t data_offset = offsetof(RawMessage, mdata);

// Allocate a buffer of the correct size for message
std::vector<char> msgbuf(size + data_offset);

ssize_t bytes_read;

// Read raw message
if((bytes_read = msgrcv(MSGQ_ID, &msgbuf[0], size, MSG_ID, 0)) < 0)
{
throw MsgRecvFailedException();
}

// a string encapsulates the data and the size, why not just return one
return std::string(msgbuf.begin() + data_offset, msgbuf.begin() + data_offset + bytes_read);
}

反之,您只需按照 msgsnd 接口(interface)的要求将数据打包到一个 struct hack 兼容数据数组中。正如其他人指出的那样,这不是一个好的接口(interface),但掩盖了实现定义的行为和对齐问题,这样的事情应该可行。

例如

void SendMessage(const std::string& data)
{
extern int MSGQ_ID; // message queue id, should be a parameter??
extern long MSG_ID; // message type, should be a parameter??

// ugly struct hack required by msgsnd
struct RawMessage {
long mtype;
char mdata[1];
};

size_t data_offset = offsetof(RawMessage, mdata);

// Allocate a buffer of the required size for message
std::vector<char> msgbuf(data.size() + data_offset);

long mtype = MSG_ID;
const char* mtypeptr = reinterpret_cast<char*>(&mtype);

std::copy(mtypeptr, mtypeptr + sizeof mtype, &msgbuf[0]);
std::copy(data.begin(), data.end(), &msgbuf[data_offset]);

int result = msgsnd(MSGQ_ID, &msgbuf[0], msgbuf.size(), 0);
if (result != 0)
{
throw MsgSendFailedException();
}
}

关于c++ - 如何从消息队列接收动态长度数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1181816/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com