C++之IPC测试单元

20 篇文章 0 订阅
4 篇文章 0 订阅

# 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


# Makefile

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的数据文件,可以一次性发送多条
******************************************************************************/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值