我必须使用 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
连续存储其组件,一旦知道缓冲区的大小,就可以调整 char
的 vector
的大小并使用这个用来保存缓冲区。使用 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/