# cstringuitls.h
#ifndef CSTRINGUTILS_H
#define CSTRINGUTILS_H
#include <vector>
#include <string>
#include <iostream>
#include <map>
using namespace std;
class CStringUtils
{
public:
static int split(const string & str,vector<string>& ret_,string sep);
static int getXmlNodeValue(const string src ,const string key ,string & value);
static string toString(int n);
static int StringToInt(string str);
};
#endif // CSTRINGUTILS_H
# cstringuitls.cpp
#include "cstringutils.h"
#include <stdlib.h>
#include <strstream>
/**************************************************************************************************
* split string to stringList.
*************************************************************************************************/
int CStringUtils::split(const string &str, vector<string> &ret_, string sep){
if (str.empty())
return 0;
string tmp;
string::size_type pos_begin = str.find_first_not_of(sep);
string::size_type comma_pos = 0;
while (pos_begin != string::npos)
{
comma_pos = str.find(sep, pos_begin);
if (comma_pos != string::npos)
{
tmp = str.substr(pos_begin, comma_pos - pos_begin);
pos_begin = comma_pos + sep.length();
}
else
{
tmp = str.substr(pos_begin);
pos_begin = comma_pos;
}
if (!tmp.empty())
{
ret_.push_back(tmp);
tmp.clear();
}
}
return 0;
}
/**************************************************************************************************
* get Xml node`s value from string.
*************************************************************************************************/
int CStringUtils::getXmlNodeValue(const string src ,const string key ,string & value){
string sNode = "<" + key + ">";
string eNode = "</" + key + ">";
int begin = src.find(sNode ,0);
if (string::npos == begin){
return -1;
}
int end = src.find(eNode ,begin);
if (string::npos == end){
return -1;
}
value = src.substr(begin + sNode.length() , end - begin - sNode.length());
return 1;
}
/**************************************************************************************************
* Convert INT to String.
*************************************************************************************************/
string CStringUtils::toString(int n){
strstream m;
m<<n;
string s;
m>>s;
return s;
}
/**************************************************************************************************
* Convert String to INT32
*************************************************************************************************/
int CStringUtils::StringToInt(string str){
strstream m;
m<<str;
int n;
m>>n;
return n;
}
# fileParser.h
#ifndef FILEPARSER_H
#define FILEPARSER_H
#include <string>
#include <vector>
using namespace std;
typedef vector<string> Record;
class FileManager{
public:
static FileManager * getInstance();
bool load(const string & fname);
private:
FileManager(){
m_isLoaded = false;
m_rcList.clear();
}
~FileManager(){
}
bool parseBuffeToRecord(const char * buffer, Record & record);
public:
bool m_isLoaded;
vector<Record> m_rcList;
};
#endif
# fileParser.cpp
#include "fileParser.h"
#include "cstringutils.h"
#include <strstream>
#include <iostream>
#include <string>
#include <stdio.h>
#include <string.h>
#include <iterator>
using namespace std;
string toString(int n){
strstream m;
m<<n;
string s;
m>>s;
return s;
}
int toINT(string str){
strstream m;
m<<str;
int n;
m>>n;
return n;
}
static FileManager * g_instance = NULL;
/******************************************************************************/
FileManager * FileManager::getInstance(){
if (g_instance == NULL)
g_instance = new FileManager();
return g_instance;
}
/******************************************************************************/
bool FileManager::load(const string & fname){
if (m_isLoaded){
cout << __FUNCTION__ << "::\t" << "Config file is loaded." << endl;
return true;
}
FILE * fp = fopen(fname.c_str(),"r");
if ( fp == NULL){
cout << __FUNCTION__ << "::\t" << "fopen() failed ,please make sure " << fname << "exist" << endl;
return false;
}
char buffer[100];
Record tmpNode;
while(true){
memset(buffer,'\0',sizeof(buffer));
char * ret = fgets(buffer, sizeof(buffer), fp);
if (ret == NULL){
cout << __FUNCTION__ << "::\t" << "fgets() read eof." << endl;
break;
}
tmpNode.clear();
bool iRet = parseBuffeToRecord(buffer, tmpNode);
if ( false == iRet)
{
continue;
}
m_rcList.push_back(tmpNode);
}
fclose(fp);
}
bool FileManager::parseBuffeToRecord(const char * buffer, Record & record){
if ( NULL == buffer)
{
cout << __FUNCTION__ << "::\t" << "Parsed Buffer is NULL!" << endl;
return false;
}
CStringUtils::split(string(buffer), record, "\t");
#ifdef DDEBUG
cout << __FUNCTION__ << "::\t" << "Parsed Result :\n==============" << endl;
for ( int i = 0;i < record.size();i++ )
{
cout << record[i] << "\t";
}
cout << __FUNCTION__ << "::\t" << "\n==============" << endl;
#endif
return true;
}
# main.cpp
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <curses.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>
#include "fileParser.h"
#include "message.h"
#include <string>
using namespace std;
static int g_msg_type; //表示接受的IPC的消息类型
static char g_dest_flag; //表示目标的IPC标识符
static char g_src_flag; //表示自身IPC的标识符
static string g_ftok_path; //表示ftok()的首个path参数
static string g_msg_file; //表示默认的消息发送文件
static int s_src_id;
static int s_dest_id;
int process_args(int argc,char **argv);
int createMsgQueue(string & ftokPath, int msgQueType);
void * onRecvMsg(void * p){
pthread_detach(pthread_self());
Message msg;
cout << "Enter SendMsg Thread..." << endl;
int msg_len = 0;
while(1)
{
msg_len = msgrcv(s_src_id, &msg, sizeof(Message) - sizeof(long), g_msg_type, 0 | MSG_NOERROR);
displayMessage(&msg);
usleep(100);
}
}
void * onSendMsg(void * p){
pthread_detach(pthread_self());
FileManager * instance = FileManager::getInstance();
instance->load(g_msg_file.c_str());
cout << "Enter RecvMsg Thread..." << endl;
string ch;
char flag;
int r_len;
while(1)
{
cout << "Start Send Command:" << endl;
cin >> ch;
if ( (ch != "exit") || (ch != "q") || (ch != "quit") )
{
for(int i = 0;i < instance->m_rcList.size();i++)
{
Message tmp;
memset(&tmp,'\0',sizeof(Message));
tmp.type = g_msg_type;
Record rc = instance->m_rcList[i];
for (int k = 0;k < rc.size();k++)
{
string val = rc[k];
if (val.size() == 0)
{
cout << "This Record is invalid" << endl;
break;
}
setMessageValue(&tmp, k+1,val);
}
displayMessage(&tmp);
int iRet = msgsnd(s_dest_id, &tmp, sizeof(Message) - sizeof(long), IPC_NOWAIT);
if ( iRet != 0)
{
cout << "msgsnd error, errno:" << errno << endl;
}
cout << "Next Command ?:" << endl;
cin >> ch;
}
}
else
{
cout << "Send Thread Will Exit..." << endl;
}
}
}
int main(int argc,char **argv){
/*Step:解析命令行参数*/
process_args(argc,argv);
/*Step2:创建收发消息队列*/
s_src_id = createMsgQueue(g_ftok_path, g_src_flag);
s_dest_id = createMsgQueue(g_ftok_path, g_dest_flag);
cout << "src_queue_id::" << s_src_id << endl;
cout << "dest_queue_id::" << s_dest_id << endl;
/*Step3:创建收发线程*/
pthread_t sndTid;
pthread_t rcvTid;
pthread_create(&sndTid, NULL, onSendMsg, NULL);
pthread_create(&rcvTid, NULL, onRecvMsg, NULL);
pthread_join(sndTid,NULL);
pthread_join(rcvTid,NULL);
return 0;
}
/******************************************************************************
* 参数说明:
* -d : dest ,表示目标消息队列的标识符(如:a , b c ...)
* -s : src ,表示源消息队列标识符(如:a , b , c ...)
* -p : path ,表示创建ftok()中的首个参数path
* -t : type ,表示消息的类型
* -m : msgfile,表示需要发送的Message的数据文件,可以一次性发送多条
******************************************************************************/
int process_args(int argc,char **argv)
{
int oc;
char * pOption = NULL;
while((oc = getopt(argc, argv, "t:s:p:d:m:")) != -1)
{
switch(oc)
{
/*消息类型*/
case 't':
{
pOption = optarg;
if ( NULL == pOption)
{
g_msg_type = 1;
}
else
{
g_msg_type = atoi(pOption);
}
}
break;
/*目标-标识符*/
case 'd':
{
pOption = optarg;
if ( NULL == pOption)
{
g_dest_flag = 'd';
}
else
{
g_dest_flag = pOption[0];
}
}
break;
/*源-标识符*/
case 's':
{
pOption = optarg;
if ( NULL == pOption)
{
g_src_flag = 's';
}
else
{
g_src_flag = pOption[0];
}
}
break;
/*ftok基础路径*/
case 'p':
{
pOption = optarg;
if ( NULL == pOption)
{
g_ftok_path = "/usr/";
}
else
{
g_ftok_path = pOption;
}
}
break;
/*msg-消息文件*/
case 'm':
{
pOption = optarg;
if ( NULL == pOption)
{
g_msg_file = "msg.txt";
}
else
{
g_msg_file = pOption;
}
}
break;
}
}
}
/******************************************************************************
* 参数说明:
* 创建消息队列
******************************************************************************/
int createMsgQueue(string & ftokPath, int msgQueType)
{
int msgQueId=0;
key_t msgQueKey=0;
msgQueKey = ftok(ftokPath.c_str(), msgQueType);
if((msgQueId = msgget(msgQueKey,IPC_CREAT | 0666)) < 0)
{
cout << "create msg queue faile!" << endl;
return 0;
}
else
{
cout << "create msg queue success!msg id:" << msgQueId << endl;
return msgQueId;
}
return -1;
}
# message.h
#ifndef MESSAGE_H
#define MESSAGE_H
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
using namespace std;
typedef struct _Message{
long type;
int id;
char data[10];
char buffer[20];
} Message;
//#define OUT(p) cout << "msg->p::" << msg->p << endl
#define OUT(p) cout << msg->p << endl
void displayMessage(Message * msg){
if ( NULL == msg)
{
cout << "Message is NULL" << endl;
return;
}
OUT(type);
OUT(id);
OUT(data);
OUT(buffer);
}
void setMessageValue(Message * msg,int id,string val)
{
if (id == 1) msg->id = atoi(val.c_str());
if (id == 2) strcpy(msg->data ,val.c_str());
if (id == 3) strcpy(msg->buffer, val.c_str());
}
#endif
# msgA.txt
10 Afeihf Ahhh
20 Azenzhe Ayyy
30 Apangan Axxx
TARGET=msgclient
INCLUDES=-I.
LIBS=-lpthread
SOURCES=main.cpp cstringutils.cpp fileParser.cpp message.h
$(TARGET):
g++ $(SOURCES) -o $(TARGET) $(INCLUDES) $(LIBS)
clean:
rm -rf $(TARGET) *.o *~
# 用法说明
./msgclient -d A -s B -p /usr/ -t 1 -m msgA.txt
=====================================
/******************************************************************************
* 参数说明:
* -d : dest ,表示目标消息队列的标识符(如:a , b c ...)
* -s : src ,表示源消息队列标识符(如:a , b , c ...)
* -p : path ,表示创建ftok()中的首个参数path
* -t : type ,表示消息的类型
* -m : msgfile,表示需要发送的Message的数据文件,可以一次性发送多条
******************************************************************************/