⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 collection.cc

📁 这是一个模拟电信计费的程序,非常详细,运用了线程池、消息队列和socket编程等技术。
💻 CC
字号:
#include "collection.h"using namespace std;collection::collection(){ 	last.ut_type = -1; 	key = ftok("/dev/null",0);	if((msgid = msgget(key,0))== -1){		msgid = msgget(key,IPC_CREAT | IPC_EXCL | 0600);		if(msgid < 0) exit(-1);	}}	collection::~collection(){		dump_lastposition();		dump_unfinished();		multimap<short,utmpx*>::iterator it;		for(it = login.begin(); it!=login.end();it++)			delete it->second;		for(it = logoff.begin(); it!=logoff.end();it++)			delete it->second;		list<info*>::iterator it2;		for(it2 = data.begin(); it2 != data.end();it2++)			delete *it2;				}void collection::setdefault(){	backup_file = BACKUP;	position_file = POSITION;	system_file = SYSTEM;}string collection::localIP(){	static string ip = NOT_ASSIGNED;	if(ip == NOT_ASSIGNED)	{		char* name = new char[255];		gethostname(name,255);		hostent* h = gethostbyname(name);		inet_ntop(AF_INET,h->h_addr_list[0],name,16);		ip = name;		delete name;	}	return ip;}void collection::loadconfiguration(const char* file){	if(file == NULL)	{		setdefault();	}	else	{		if(access(file,F_OK)<0){  		setdefault();		}		else		{			ifstream fin(file);			if(!fin)			{				setdefault();			}			else			{				while(!fin.eof())				{					char buf[MAX_BUF];					memset(buf,0x00,MAX_BUF);					fin.getline(buf,MAX_BUF);					string input = buf;					if(input.find(COMMENT_TAG,0) != input.npos) continue;					if(input.find(BACKUP_TAG,0) != input.npos){						backup_file = input.erase(0,input.find(DELIMITER_TAG,0)+1);					}					if(input.find(POSITION_TAG,0) != input.npos){						position_file = input.erase(0,input.find(DELIMITER_TAG,0)+1);					}					if(input.find(SYSTEM_TAG,0) != input.npos){						system_file = input.erase(0,input.find(DELIMITER_TAG,0)+1);					}				}//end of while(!fin.eof())				fin.close();			}//end of else [if(!fin)]		}//end of else [if(access(file,F_OK)<0)]	}//end of else [if(file == NULL)]	#ifdef __DEBUG	cout << " BACKUP =" << backup_file << endl;	cout << " POSITION =" << position_file << endl;	cout << " SYSTEM =" << system_file << endl;	#endif}//end of functionvoid collection::retrieve(){	utmpx* tmp;		#ifdef __TIMER	_timer.start("collection::retrieve");	#endif		//check backup	if(access(backup_file.c_str(),F_OK)==0){		ifstream ifs(backup_file.c_str(),ios::in | ios::binary);		while(1)		{			utmpx* p;			p = new utmpx;			ifs.read((char*)p,sizeof(utmpx));			if(ifs.eof()) break;			login.insert(pair<short,utmpx*>(p->ut_pid,p));			}		ifs.close();	}	//load system file	//set position	if(access(position_file.c_str(),F_OK)==0)	{		utmpxname(position_file.c_str());		setutxent();		utmpx* pos = new utmpx;		tmp = getutxent();		memcpy(pos,tmp,sizeof(utmpx));	  #ifdef __DEBUG	  show(pos);	  #endif		endutxent();		utmpxname(system_file.c_str());		setutxent();		tmp = getutxline(pos);		#ifdef __DEBUG		cout << endl << endl;	  show(tmp);	  #endif				while(1)		{			if(tmp == NULL) {				setutxent();				break; 			}			else if(tmp->ut_tv.tv_sec != pos->ut_tv.tv_sec)			{				getutxent();				tmp = getutxline(pos);			}			else break;		}		#ifdef __DEBUG		cout << " ------------ " << endl;	  show(tmp);	  #endif				delete pos;	}	else	{		utmpxname(system_file.c_str());		setutxent();	}	while((tmp = getutxent()) != NULL)	{		if(tmp->ut_type == USER_PROCESS)		{			utmpx* t = new utmpx;			memcpy(t,tmp,sizeof(utmpx));			login.insert(pair<short,utmpx*>(tmp->ut_pid,t));			memcpy(&last,tmp,sizeof(last));		}		if(tmp->ut_type == DEAD_PROCESS)		{			utmpx* t = new utmpx;			memcpy(t,tmp,sizeof(utmpx));			logoff.insert(pair<short,utmpx*>(tmp->ut_pid,t));		}				#ifdef __DEBUG		printf("\x0d\tLogin: %d\tLogoff: %d",login.size(), logoff.size());		#endif	}	#ifdef __DEBUG	utmpx* u = &last;	show(u);	cout << endl;	#endif	endutxent();	#ifdef __TIMER	_timer.end();	_timer.show();	#endif}int collection::processing(){	#ifdef __DEBUG	int s = login.size();	int count = 0;	#endif	multimap<short,utmpx*>::iterator it = login.begin();	#ifdef __TIMER	_timer.start("collection::processing");	#endif	for(it = login.begin();it != login.end();it++)	{		time_t min = -1;		multimap<short,utmpx*>::iterator start,end,matched;		start = logoff.lower_bound(it->first);				end = logoff.upper_bound(it->first);		matched = logoff.end();		if(start == end && start == logoff.end()) continue;		while(start != end)		{			if(start->second->ut_tv.tv_sec > it->second->ut_tv.tv_sec			  && !strcmp(start->second->ut_name,it->second->ut_name)) 			{				if(min == -1) {					matched = start;					min = start->second->ut_tv.tv_sec - it->second->ut_tv.tv_sec;				}				else				{					if(start->second->ut_tv.tv_sec - it->second->ut_tv.tv_sec < min &&					start->second->ut_tv.tv_sec - it->second->ut_tv.tv_sec > 0) {						min = start->second->ut_tv.tv_sec - it->second->ut_tv.tv_sec;						matched = start;					}				}			}			start++;		}		if(matched != logoff.end())		{			store(it->second,min);			#ifdef __DEBUG			count++;			#endif			login.erase(it);			it--;			logoff.erase(matched);		}	}	#ifdef __DEBUG	printf("\nThere are %d matched. \n", count);	#endif	////sending finish	/*	msg _msg;	_msg.mtype = END;	while(msgsnd(msgid,&_msg,sizeof(_msg),0)) sleep(1);	*/	#ifdef __TIMER	_timer.end();	_timer.show();	cout << " there are still " << login.size() << " login no matched." << endl;	#endif	return 0;}void collection::store(const utmpx* u, const time_t& t){		info inf;		memset(&inf,0x00,sizeof(inf));		strcpy(inf.user_name,u->ut_name);		inf.start_time = u->ut_tv.tv_sec;		inf.duration = t;		strcpy(inf.IP,localIP().c_str());		//data.push_back(inf);				msg _msg;		_msg.mtype = 1;		memcpy(&_msg.inf,&inf,sizeof(info));		#ifdef __DEBUG		/*cout << " ***************** " << endl;		cout << inf.user_name << "\t" <<	inf.duration << "\t";		cout << inf.IP << endl; 		cout << " ***************** " << endl;		*/		#endif		while(msgsnd(msgid,&_msg,sizeof(_msg),IPC_NOWAIT)) sleep(1);		}void collection::dump_unfinished(){	remove(backup_file.c_str());	string cmd = "touch " + string(backup_file);	system(cmd.c_str());	int fd = open(backup_file.c_str(),O_WRONLY);	if(fd < 0) {		#ifdef __DEBUG		cout << " cannot open file for output." << endl;		#endif		return;	}	for(multimap<short,utmpx*>::iterator it = login.begin(); it != login.end(); it++)	{						if(write(fd,(char*)(it->second),sizeof(utmpx))<0)			{				#ifdef __DEBUG				perror("write");				#endif			}	}	close(fd);	}void collection::dump_lastposition(){	if(last.ut_type == -1) return;	remove(position_file.c_str());	string cmd = "touch " + string(position_file);	system(cmd.c_str());	utmpxname(position_file.c_str());	setutxent();	pututxline(&last);	endutxent();		}void collection::show(struct utmpx*& tmp){	cout << tmp->ut_user << endl;	cout << tmp->ut_id << endl;	cout << tmp->ut_line << endl;	cout << tmp->ut_pid << endl;	cout << tmp->ut_type << endl;	cout << tmp->ut_tv.tv_sec << endl;	}void collection::start_cllection(){	retrieve();	processing();}void collection::receive(){	msg _msg;	while(msgrcv(msgid,&_msg,sizeof(msg),0,0)>0)	{		info * _inf;		_inf = new info;		if(_msg.mtype == END) break;		memcpy(_inf,&_msg.inf,sizeof(info));		#ifdef __DEBUG		//cout << _inf->user_name << "\t" <<	_inf->duration << "\t";		//cout << _inf->IP << endl; 		#endif		data.push_back(_inf);	}		#ifdef __DEBUG	cout << " Threre are " << data.size() << " records matched" << endl;	ofstream fout("result.txt");	fout << " Threre are " << data.size() << " records matched" << endl;	for(list<info*>::iterator it = data.begin(); it!= data.end(); it++)	{		fout << (*it)->user_name << "\t" <<	(*it)->duration << "\t";		fout << (*it)->IP << endl;	}	fout.close();	#endif}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -