writer:lIcht email:lIcht.gzl@gmail.com date: 2021.7.28
使用情景:udp通讯实现指令的接收和发送,在linux下进行c++的多线程编程,接收和发送在不同线程,主线程则负责监听ROS系统中的消息,发送的UDP指令需要根据接收到的UDP指令进行选择, 这就需要在发送和接收线程进行消息传递。
(1)首先,在线程外创建系一个系统的消息队列,实现方法:
x
key_t m_udpMsgKey = ftok(".", 89);
int m_udpMsgId = msgget(m_udpMsgKey, IPC_CREAT | 0x0666);
其中,m_udpMsgKey为申请消息队列的key值,m_udpMsgId为申请的消息队列id,如果两者任一的值为-1则表示创建失败。
(2)创建好消息队列后需要在数据处理处将即将发送的数据存进消息队列:
x
// 首先需要定义消息的格式,以结构体形式
struct msgBuf
{
long int msgType;
char data[512];
}
//然后在发送时将数据传入结构体的data部分,并给架构体第一个值赋大于零的值,表示消息的类型
//buff为要发送的数据
char buff[] = "hello world";
msgBuf mbuf;
mbuf.msgType = 1;
//拷贝数据进结构体的数据部分
memcpy(&mbuf.data, buff, sizeof(buff));
//调用msgsnd将数据存入消息队列
msgsnd(m_udpMsgID, &mbuf, 512, 0);
需注意的点:1、结构体中msgtype的值需要大于0;
2、msgsnd方法中第三个参数的值为结构体中数据部分的长度,而非整个结构体(是data的长度即512,而不是msgBuf的长度即sizeof(msgBuf))的长度;
(3)取出消息队列中的数据进行处理:
xxxxxxxxxx
//在取消息队列端也需要根据申请消息队列的相关值,与申请创建队列时大致相同
key_t mKey = ftok(".". 89);
int msgid = msgget(mKey, 0);
//定义消息队列的结构体将消息取出
msgBuf mbuf;
msgrcv(msgid, &mbuf, 512, 1, IPC_NOWAIT);
需注意的点:1、mKey的获取ftok方法中第二个参数要与申请时相同;
2、msgrcv方法中第三个参数与msgsnd一样,为结构体数据部分的长度,第四个参数的值为消息的类型,即msgType的值,如果设置为0,则表示接收任何类型的消息;
(4)程序结束时需要从系统中删除创建的消息队列,不然下次启动会报错,下次启动程序无法成功创建
xxxxxxxxxx
msg(m_udpMsgid, IPC_RMID, NULL);
将创建队列时的消息队列id作为第一个参数。