如何从消息队列接收动态长度数据? [英] How to receive dynamic length data from a message queue?
问题描述
我必须使用大学项目的SysV消息队列发送和接收动态数据。
I have to send and receive dynamic data using a SysV message queue for a university project.
数据的长度以单独的消息 size
是已知的。
The length of the data is transmitted in a separate message, size
is therefor already known.
这是我如何尝试接收数据。我必须承认我不是C ++专家,特别是在内存分配方面。
And this is how I try to receive the data. I have to admit that I'm not a C++ specialist, especially when it comes to memory allocation.
struct {
long mtype;
char *mdata;
} msg;
msg.mdata = (char *)malloc(size * sizeof(char));
msgrcv(MSGQ_ID, &msg, size, MSG_ID, 0);
问题似乎是 malloc
,但我不知道该如何做。
The problem seems to be the malloc
call, but I don't know how to do this right.
EDIT
我试着在邮件队列周围的一个OO包装中有一个 read 方法。我想读取消息队列中的数据到 char []
或 std :: string
。我现在看起来(简化)像这样。
What I try is to have a some sort of read method in a OO wrapper around the message queues. I'd like to read the data in the message queue into a char[]
or a std::string
. What I have now looks (simplified) like this.
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;
}
所有我得到的是分段错误或完全损坏的数据
All I get is segmentation faults or completely corrupt data (although this data sometimes contains what I want).
推荐答案
不能将指针传递给包含 std :: string 成员到
msgrcv
,这违反了接口契约。
You can't pass a pointer to a structure that contains a std::string
member to msgrcv
, this violates the interface contract.
传递给 msgrcv
的参数需要指向一个具有足够空间的缓冲区,以存储 struct {long mtype; char mdata [size]; };
其中size是 msgrcv
的第三个参数。
The second parameter passed to msgrcv
needs to point to a buffer with sufficient space to store a 'plain' C struct of the form struct { long mtype; char mdata[size]; };
where size is the third parameter to msgrcv
.
这个缓冲区的大小可能取决于 size
,因为可能的对齐问题,但是你必须假定它不在提供这种接口的系统上。您可以使用标准的 offsetof
宏来帮助确定此大小。
Unfortunately, determining the size of this buffer might depend on size
due to possible alignment issues but you have to assume that it doesn't on a system that provides this sort of interface. You can use the standard offsetof
macro to help determine this size.
作为
连续存储其组件,一旦知道缓冲区的大小,就可以调整 char $>的
向量
c $ c>并使用它来保存缓冲区。使用向量
可以免除您免费
或 delete []
手动。
As a vector
stores its components contiguously, once you know the size of the buffer, you can resize a vector
of char
and use this to hold the buffer. Using a vector
relieves you of the obligation to free
or delete[]
a buffer manually.
您需要这样做。
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);
}
换句话说,你只需将数据打包到 struct
hack兼容数据数组,如msgsnd接口所需。因为其他人有指针,它不是一个好的界面,但掩盖了实现定义的行为和对齐的关注,这样的东西应该工作。
To go the other way, you just have to pack the data into a struct
hack compatible data array as required by the msgsnd interface. As others have pointer out, it's not a good interface, but glossing over the implementation defined behaviour and alignment concerns, something like this should work.
例如
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();
}
}
这篇关于如何从消息队列接收动态长度数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!