消息队列是进程间通信方式之一,该文章讲解如何使用消息队列,关于消息队列的基础知识,请同学们自行学习。
本列子实现一个简单的client,server;client负责放置消息到消息队列中,server负责读出消息队列。
//MsgQ操作封装
#ifndef _MY_MSG_QUEUE_
#define _MY_MSG_QUEUE_
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string>
class MsgQueue
{
public:
MsgQueue():m_msgId(-1){}
~MsgQueue(){}
#define MAX_LENGTH 1024*50
struct _msg_struct_
{
long type;
char msg[MAX_LENGTH]; //max buffer is 50k
};
public:
int InitQueue(unsigned int key)
{
if((m_msgId = msgget((key_t)key,0666|IPC_CREAT)) < 0 )
{
m_errmsg = strerror(errno);
return -1;
}
return 0;
}
int PutOne(const std::string str, long type = 9999)
{
if(m_msgId == -1)
{
m_errmsg = "Not Init";
return -1;
}
if(str.length() > MAX_LENGTH)
{
m_errmsg = "Msg Too large";
return -2;
}
struct _msg_struct_ s_data;
s_data.type = type;
memcpy(s_data.msg, str.c_str(), str.length());
int ret = msgsnd(m_msgId, (void*)&s_data, str.length(), IPC_NOWAIT);
if(ret < 0)
{
m_errmsg = strerror(errno);
return -3;
}
return 0;
}
int GetOne(std::string &strOut, long type = 0)
{
if(m_msgId == -1)
{
m_errmsg = "Not Init";
return -1;
}
struct _msg_struct_ s_data;
ssize_t size = msgrcv(m_msgId, (void*)&s_data, MAX_LENGTH, type, IPC_NOWAIT);
if(size < 0)
{
m_errmsg = strerror(errno);
return -2;
}
strOut.assign(s_data.msg, size);
return size;
}
std::string GetLastErrMsg()
{
return m_errmsg;
}
private:
int m_msgId;
std::string m_errmsg;
};
#endif
Client实现如下
#include "MsgQueue.h"
#include <iostream>
#define MSG_KEY 11021
#define MSG_TYPE 11011
int main(int argc, char**argv)
{
MsgQueue msgQ;
int iResult = msgQ.InitQueue(MSG_KEY);
if(iResult)
{
std::cerr<<"Msgq Init Failed,ErrMsg:"<<msgQ.GetLastErrMsg()<<std::endl;
return iResult;
}
std::string strMsg="www.google.hk.com";
iResult = msgQ.PutOne(strMsg,MSG_TYPE);//放置消息到msgq中
if(iResult)
{
std::cerr<<"Msgq PutOne Failed,ErrMsg:"<<msgQ.GetLastErrMsg()<<std::endl;
return iResult;
}
std::cout<<"Client Put Msg Finished!!"<<std::endl;
}
Server的实现如下:
#include "MsgQueue.h"
#include <iostream>
#define MSG_KEY 11021
#define MSG_TYPE 11011
int main(int argc, char**argv)
{
MsgQueue msgQ;
int iResult = msgQ.InitQueue(MSG_KEY);
if(iResult)
{
std::cerr<<"Msgq Init Failed,ErrMsg:"<<msgQ.GetLastErrMsg()<<std::endl;
return iResult;
}
std::string strMsg;
iResult = msgQ.GetOne(strMsg,MSG_TYPE);//从msgq中读取消息
if(iResult<0)
{
std::cerr<<"Msgq GetOne Failed,ErrMsg:"<<msgQ.GetLastErrMsg()<<",Result:"<<iResult<<std::endl;
return iResult;
}
std::cout<<"Server Get Msg Finished,Msg:"<<strMsg<<std::endl;
}
g++ server.cpp -o server
g++ client.cpp -o client
在生产和消费的过程中,可以通过系统命令ipcs来查看消息队列的消息情况。