目录
我的Spellcorrect开发文档
相关配置文件及准备工作:
演示效果(中文):
演示效果(英语):
代码部分:
相关配置文件及准备工作:
演示效果(中文):
演示效果(英语):
代码部分:
---恢复内容开始---
我的Spellcorrect开发文档
相关配置文件及准备工作:
我的主要文件夹分为三个:分别为客户端,cppjieba分词库,离线部分及服务器部分
1560856582308
客户端部分:内部为客户端源码及运行程序
1560856552431
cppjieba分词库部分,就不赘述,请自行安装
离线部分:内部有中英文件夹放置索引及词典文件,还有配置文件及分词库,其余为代码
1560857073864
服务器部分:最为重要的配置文件及数据部分,头文件在include,实现文件在src里面
1560857034230
演示效果(中文):
==启动时服务器:==
1560857677039
==客户端连入时时服务器:==
1560857739202
==输入“赵”==
1560858117388
==输入“周杰伦”==
1560858201376
==输入清华大学==
1560858560147
演示效果(英语):
==启动时服务器:==
1560857677039
==客户端连入时时服务器:==
1560857739202
==输入student:==
1560858008297
==输入spell:==
1560858872540
==输入computer:==
1560859162357
代码部分:
离线部分:
img
==Makefile:==
SRCS:=$(wildcard*.cc)
OBJS:=$(patsubst%.cc,%.o,$(SRCS))
CXX:=g++
CXXFLAGS:=-w-g-std=c++11$(addprefix-I,$(INC_DIR))$(LIBS)-Wno-deprecated-I../cppjieba/include/-I../cppjieba/deps
EXE:=./main
$(EXE):$(OBJS)
$(CXX)-o$(EXE)$(OBJS)$(CXXFLAGS)
clean:
rm-rf$(EXE)
rm-rf$(OBJS)
==Configuration:==
///=======================================
///File:Configuration.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-1200:30:39
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__CONFIGURATION_H__
#define__CONFIGURATION_H__
#include"Nocopyable.h"
#include<string>
#include<map>
usingnamespacestd;
classConfiguration
:publicNoncopyable
{
public:
Configuration(conststring&filePath);
stringgetEnglishDir()const{return_englishDir;}
stringgetChineseDir()const{return_chineseDir;}
private:
string_filePath;
string_englishDir;
string_chineseDir;
};
template<typenameT>
classSingleton
{
public:
template<typename...Args>
staticT*getInstance(Args...args)
{
if(!_pInstance)
_pInstance=newT(args...);
return_pInstance;
}
staticvoiddestroy()
{
if(_pInstance)
delete_pInstance;
}
private:
Singleton();
~Singleton();
staticT*_pInstance;
};
template<typenameT>
T*Singleton<T>::_pInstance=NULL;
#endif
1///=======================================
2///File:Configuration.cc
3///Author:wtptorres(1584292712@qq.com)
4///Date:2019-06-1200:30:04
5///Dream:Don'tforgetyourdreams!
6///======================================
7
8
9#include"Configuration.h"
10#include<utility>
11#include<fstream>
12#include<iostream>
13usingnamespacestd;
14
15Configuration::Configuration(conststring&filePath)
16:_filePath(std::move(filePath))
17{
18ifstreamifs(_filePath);
19if(!ifs)
20cout<<"fileopenerror!"<<endl;
21ifs>>_englishDir;
22ifs>>_chineseDir;
23ifs.close();
24}
///=======================================
///File:Nocopyable.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-1200:24:36
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__NOCOPYABLE_H__
#define__NOCOPYABLE_H__
classNoncopyable
{
public:
Noncopyable()=default;
~Noncopyable()=default;
private:
Noncopyable(constNoncopyable&rhs);
Noncopyable&operator=(constNoncopyable&rhs);
};
#endif
==DictProducer:==
///=======================================
///File:DictProducer.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-1216:40:25
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__DICTPRODUCER_H__
#define__DICTPRODUCER_H__
#include"SplitTool.h"
usingnamespacestd;
#include"Nocopyable.h"
#include<memory>
#include<string>
#include<vector>
#include<map>
#include<utility>
classDictProducer
:publicNoncopyable
{
public:
DictProducer(conststring,conststring,conststring&,SplitToolJieba*);
~DictProducer(){}
voidbuild_dict();
voidbuild_cn_dict();
voidstore_dict();
vector<pair<string,int>>&getIndict(){return_indict;}
private:
voidprocessEnglishWord(string&word);
voidprocessChineseWord(string&word);//除去中文的数字
voidconstruct_indict();
string_englishDir;
string_chineseDir;
string_goleFilePath;
vector<string>_englishFiles;
vector<string>_chineseFiles;
map<string,int>_dict;
vector<pair<string,int>>_indict;
shared_ptr<SplitToolJieba>_splitTool;
};
#endif
///=======================================
///File:DictProducer.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-1216:50:46
///Dream:Don'tforgetyourdreams!
///======================================
#include"DictProducer.h"
#include<cctype>
#include<utility>
#include<fstream>
#include<iostream>
#defineFIRSTSIZE10000
usingnamespacestd;
DictProducer::DictProducer(conststringenglishDir,conststringchineseDir,conststring&goleFilePath,SplitToolJieba*splitToolPtr)
:_englishDir(englishDir)
,_chineseDir(chineseDir)
,_goleFilePath(goleFilePath)
{
_splitTool.reset(splitToolPtr);
std::ifstreamifsEnglish(_englishDir);
std::ifstreamifsChinese(_chineseDir);
stringfilePath;
if(!ifsEnglish||!ifsChinese){
cout<<"Dictfileopenerror!"<<endl;
}
while(ifsEnglish>>filePath)
{
_englishFiles.push_back(filePath);
}
while(ifsChinese>>filePath)
{
_chineseFiles.push_back(filePath);
}
_indict.reserve(FIRSTSIZE);
}
voidDictProducer::processEnglishWord(string&word)
{
autocit=word.begin();
for(;cit!=word.end();++cit)
{//去除标点符号或数字
if(!isalpha(*cit)){
word.erase(cit);
--cit;//迭代器位置发生改变
}elseif(isupper(*cit)){//将大写字母改为小写
*cit=tolower(*cit);
}
}
}
voidDictProducer::processChineseWord(string&word)
{
autocit=word.begin();
for(;cit!=word.end();++cit)
{//去除数字
if(!isalnum(*cit)){
word.erase(cit);
--cit;
}
}
}
voidDictProducer::build_dict()//建立英文词典
{
for(auto&filePath:_englishFiles)
{
ifstreamifs(filePath);
if(!ifs){
cout<<"EnglishFileopenerror!"<<endl;
}
stringword;
while(ifs>>word)
{
processEnglishWord(word);
autocit=_dict.find(word);
if(word.size()>0&&cit==_dict.end()){
_dict.insert(std::make_pair(word,1));
}elseif(cit!=_dict.end()){
++cit->second;
}
}
}
}
voidDictProducer::build_cn_dict()
{
vector<string>words;
for(autofilePath:_chineseFiles)
{
ifstreamifs(filePath);
if(!ifs){
cout<<"Chinesefileopenerror!"<<endl;
}
stringsentence;
while(std::getline(ifs,sentence))
{
_splitTool->Cut(sentence);
}
}
vector<string>&results=_splitTool->getResult();
for(auto&res:results)
{
processChineseWord(res);
autocit=_dict.find(res);
if(cit==_dict.end()){
_dict.insert(std::make_pair(res,1));
}else{
++cit->second;
}
}
}
voidDictProducer::store_dict()
{
construct_indict();
ofstreamofs(_goleFilePath);
if(!ofs)
cout<<"Store_dictopenfileerror!"<<endl;
for(auto&mypair:_indict)
{
ofs<<mypair.first<<""<<mypair.second<<endl;
}
ofs.close();
}
voidDictProducer::construct_indict()
{
for(autodictpair:_dict){
_indict.push_back(dictpair);
}
}
==GetIndex:==
///=======================================
///File:GetIndex.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-1208:52:04
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__GETINDEX_H__
#define__GETINDEX_H__
#include<string>
#include<unordered_map>
#include<set>
#include<vector>
#include<utility>
#include<unordered_set>
usingnamespacestd;
classGetIndex
{
public:
GetIndex(conststring&,conststring&,conststring&);
~GetIndex(){}
voidconstruct_index();
voidstore_index();
private:
boolisEnglish(conststring&rhs)const;
vector<string>getOneCharacter(conststring&word);
string_sourceFilePath;
string_goleFilePath;
string_stopWordsFilePath;
vector<pair<string,int>>_dict;
unordered_set<string>_stopWords;
unordered_map<string,set<int>>_index;
};
#endif
///=======================================
///File:GetIndex.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-1209:00:11
///Dream:Don'tforgetyourdreams!
///======================================
#include"GetIndex.h"
#include<fstream>
#include<sstream>
#include<iostream>
usingnamespacestd;
GetIndex::GetIndex(conststring&sourceFilePath,conststring&goleFilePath,conststring&stopWordsFilePath)
:_sourceFilePath(std::move(sourceFilePath))
,_goleFilePath(std::move(goleFilePath))
,_stopWordsFilePath(std::move(stopWordsFilePath))
{
ifstreamifs(_sourceFilePath);
if(!ifs){
cout<<"GetIndexfileopenerror!"<<endl;
}
stringline;
while(getline(ifs,line))
{
istringstreamiss(line);
stringkey;
intvalue;
iss>>key>>value;
_dict.push_back(std::make_pair(key,value));
}
ifstreamifs1(_stopWordsFilePath);
if(!ifs1){
cout<<"fileopenerror!"<<endl;
}
stringstopWord;
while(ifs1>>stopWord,!ifs1.eof())
{
_stopWords.insert(stopWord);
}
}
vector<string>GetIndex::getOneCharacter(conststring&word)
{
vector<string>tmp;
autocit=word.begin();
while(cit<word.end())
{
if(224==(*cit&224))
{
stringoneCharacter;
oneCharacter.append(cit,cit+3);
tmp.push_back(oneCharacter);
cit+=3;
}elseif(240==(*cit&240)){
stringoneCharacter;
oneCharacter.append(cit,cit+4);
tmp.push_back(oneCharacter);
cit+=4;
}else
break;
}
returntmp;
}
boolGetIndex::isEnglish(conststring&rhs)const
{
charch=*(rhs.begin());
if(ch<0)
returnfalse;
returntrue;
}
#if0
boolGetIndex::isEnglish(conststring&rhs)const
{
charch=*(rhs.begin());
if(ch<0){
returnfalse;
}
returntrue;
}
#endif
voidGetIndex::construct_index()
{
for(size_ti=0;i!=_dict.size();++i)
{
stringtmp=_dict[i].first;
if(isEnglish(tmp))
{
for(autoch:tmp)
{
stringcharactor(1,ch);
if(isalpha(ch))
{
autocit=_index.find(charactor);
if(cit==_index.end())
{
set<int>smp;
smp.insert(i);
_index.insert(std::make_pair(charactor,smp));
}else{//已经存在了该字母的索引
cit->second.insert(i);
}
}
}
}else{//中文处理部分
vector<string>oneCharacterRally=getOneCharacter(tmp);
for(autooneCharacter:oneCharacterRally)
{//stop_words中不存在该单词,则加入索引中
if(_stopWords.find(oneCharacter)==_stopWords.end()){
autoit=_index.find(oneCharacter);
if(it==_index.end()){
set<int>tmp;
tmp.insert(i);
_index.insert(std::make_pair(oneCharacter,tmp));
}else{
it->second.insert(i);
}
}
}
}
}
}
voidGetIndex::store_index()
{
//ofs存储索引的内容
std::ofstreamofs(_goleFilePath);
if(!ofs){
cout<<"fileopenerror!"<<endl;
return;
}
for(autodata:_index)
{
ofs<<data.first<<"";
for(autolinenum:data.second)
{
ofs<<linenum<<"";
}
ofs<<endl;
}
ofs.close();
}
==SplitTool:==
///=======================================
///File:SplitTool.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-1217:12:01
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__SPLITTOOL_H__
#define__SPLITTOOL_H__
#include"../cppjieba/include/cppjieba/Jieba.hpp"//需要自己将cppjieba安装在项目目录下
#include"Configuration.h"
#include<string>
#include<vector>
usingnamespacestd;
usingnamespacecppjieba;
classSplitToolJieba
{
public:
SplitToolJieba(conststring&dict_path,conststring&model_path,conststring&user_dict_path,conststring&idfPath,conststring&stopWordPath)
:_jieba(dict_path,model_path,user_dict_path,idfPath,stopWordPath)
{}
~SplitToolJieba(){}
voidCut(conststring&sentence)
{
vector<string>tmp;
_jieba.Cut(sentence,tmp);
_result.insert(_result.end(),tmp.begin(),tmp.end());
}
vector<string>&getResult(){return_result;}
private:
vector<string>_result;
cppjieba::Jieba_jieba;
};
#endif
==main:==
///=======================================
///File:main.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-1220:38:50
///Dream:Don'tforgetyourdreams!
///======================================
#include"Configuration.h"
#include"SplitTool.h"
usingnamespacestd;
#include"DictProducer.h"
#include"GetIndex.h"
#include<iostream>
#include<memory>
constchar*constDICT_PATH="../cppjieba/dict/jieba.dict.utf8";
constchar*constHMM_PATH="../cppjieba/dict/hmm_model.utf8";
constchar*constUSER_DICT_PATH="../cppjieba/dict/user.dict.utf8";
constchar*constIDF_PATH="../cppjieba/dict/idf.utf8";
constchar*constSTOP_WORD_PATH="../cppjieba/dict/stop_words.utf8";
conststringGOLE_DICT_PATH="../server/data/dict.txt";
conststringGOLE_INDEX_PATH="../server/data/index.txt";
classSplitTool;
intmain(void)
{
Configuration*pconfig=Singleton<Configuration>::getInstance("configure.txt");
SplitToolJieba*ptool=newSplitToolJieba(DICT_PATH,HMM_PATH,USER_DICT_PATH,IDF_PATH,STOP_WORD_PATH);
DictProducermydictProducer(pconfig->getEnglishDir(),pconfig->getChineseDir(),GOLE_DICT_PATH,ptool);
mydictProducer.build_dict();//建立英语词典
mydictProducer.build_cn_dict();//建立中文词典
mydictProducer.store_dict();//储存词典
GetIndexmyindex(GOLE_DICT_PATH,GOLE_INDEX_PATH,"stop_words_zh.txt");
myindex.construct_index();//建立索引
myindex.store_index();//存储索引
Singleton<Configuration>::destroy();
return0;
}
在线部分:
img
==ConFiguration:==
///=======================================
///File:ConFiguration.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0610:32:43
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__CONFIGURATION_H__
#define__CONFIGURATION_H__
#include"Noncopyable.h"
#include<string>
#include<map>
#defineCONFPATH"/home/wtp/spell/server/conf/configure.txt"
usingnamespacestd;
namespacewd
{
classConfiguration
:publicNoncopyable
{
public:
Configuration(conststring&filePath);
~Configuration()=default;
stringgetDictDir()const;
stringgetIndexDir()const;
stringgetIp()const;
stringgetCache()const;
unsignedshortgetPort()const;
private:
string_filePath;
map<string,string>_conf;
};
};
template<typenameT>
classSingleton
{
public:
template<typename...Args>
staticT*getInstance(Args...args)
{
if(!_pInstance)
_pInstance=newT(args...);
return_pInstance;
}
staticvoiddestroy()
{
if(_pInstance)
delete_pInstance;
}
private:
Singleton();
~Singleton();
staticT*_pInstance;
};
template<typenameT>
T*Singleton<T>::_pInstance=NULL;
#endif
///=======================================
///File:ConFiguration.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0715:24:14
///Dream:Don'tforgetyourdreams!
///======================================
#include"ConFiguration.h"
#include<stdlib.h>
#include<utility>
#include<fstream>
#include<iostream>
usingnamespacestd;
usingnamespacewd;
wd::Configuration::Configuration(conststring&filePath)
:_filePath(std::move(filePath))
{
ifstreamifs(_filePath);
if(!ifs){
cout<<"fileopenerror!"<<endl;
}
stringkey,value;
while(ifs>>key)
{
ifs>>value;
_conf.insert(std::make_pair(key,value));
}
ifs.close();
}
stringwd::Configuration::getDictDir()const
{
autocit=_conf.find("mydict");
if(cit==_conf.end())
return"";
else
returncit->second;
}
stringwd::Configuration::getIndexDir()const
{
autocit=_conf.find("myindex");
if(cit==_conf.end())
return"";
else
returncit->second;
}
stringwd::Configuration::getIp()const
{
autocit=_conf.find("myip");
if(cit==_conf.end())
return"";
else
returncit->second;
}
unsignedshortwd::Configuration::getPort()const
{
autocit=_conf.find("myport");
if(cit==_conf.end())
return0;
else
returnatoi(cit->second.c_str());
}
stringwd::Configuration::getCache()const
{
autocit=_conf.find("mycache");
if(cit==_conf.end())
return"";
else
returncit->second;
}
==Acceptor:==
///=======================================
///File:Acceptor.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0523:47:05
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__WD_ACCEPTOR_H__
#define__WD_ACCEPTOR_H__
#include"Socket.h"
#include"InetAddress.h"
namespacewd
{
classAcceptor
{
public:
Acceptor(intlistenfd,constInetAddress&addr);
voidready();//服务器监听准备
intaccept();//服务器接收新连接
intfd()const{return_listenSock.fd();}
private:
voidsetReuseAddr(boolon);//设置地址重用
voidsetReusePort(boolon);//设置端口重用
voidbind();//绑定
voidlisten();//监听
Socket_listenSock;
InetAddress_addr;
};
}
#endif
///=======================================
///File:Acceptor.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0523:52:12
///Dream:Don'tforgetyourdreams!
///======================================
#include<iostream>
#include"Acceptor.h"
#include"SocketUtil.h"
namespacewd
{
Acceptor::Acceptor(intlistenfd,constInetAddress&addr)
:_listenSock(listenfd)
,_addr(addr)
{}
voidAcceptor::ready()
{
setReuseAddr(true);
setReusePort(true);
bind();
listen();
}
intAcceptor::accept()
{
intpeerfd=::accept(_listenSock.fd(),NULL,NULL);
if(-1==peerfd)
{
perror("accepterror!");
}
returnpeerfd;
}
voidAcceptor::setReuseAddr(boolflag)
{
inton=(flag?1:0);
if(::setsockopt(_listenSock.fd()
,SOL_SOCKET
,SO_REUSEADDR
,&on
,static_cast<socklen_t>(size_t(on)))==-1)
{
perror("setsockoptreuseaddrerror!");
::close(_listenSock.fd());
exit(EXIT_FAILURE);
}
}
voidAcceptor::setReusePort(boolflag)
{
#ifndefSO_REUSEPORT
inton=(flag?1:0);
if(::setsockopt(_listenSock.fd()
,SOL_SOCKET
,SO_REUSEADDR
,&on
,static_cast<socklen_t>(size_t(on)))==-1)
{
perror("setsockoptreuseporterror!");
::close(_listenSock.fd());
exit(EXIT_FAILURE);
}
#else
if(flag)
{
fprintf(stderr,"SO_REUSEPORTisnotsupported!\n");
}
#endif
}
voidAcceptor::bind()
{
if(-1==::bind(_listenSock.fd()
,(conststructsockaddr*)_addr.getSockAddrPtr()
,sizeof(InetAddress)))
{
perror("binderror!");
::close(_listenSock.fd());
exit(EXIT_FAILURE);
}
}
voidAcceptor::listen()
{
if(-1==::listen(_listenSock.fd(),10))
{
perror("listenerror!");
::close(_listenSock.fd());
exit(EXIT_FAILURE);
}
}
}
#if0
intmain()
{
std::cout<<"Acceptoriscorrect!"<<std::endl;
}
#endif
==Condition.h:==
#ifndef__WD_CONDITION_H__
#define__WD_CONDITION_H__
#include"Noncopyable.h"
#include"MutexLock.h"
#include<pthread.h>
namespacewd
{
classCondition
:Noncopyable
{
public:
Condition(MutexLock&mutex)
:_mutex(mutex)
{pthread_cond_init(&_cond,NULL);}
~Condition()
{pthread_cond_destroy(&_cond);}
voidwait()
{pthread_cond_wait(&_cond,_mutex.getMutexLockPtr());}
voidnotify()
{pthread_cond_signal(&_cond);}
voidnotifyAll()
{pthread_cond_broadcast(&_cond);}
private:
pthread_cond_t_cond;
MutexLock&_mutex;
};
}
#endif
==Cache:==
///=======================================
///File:Cache.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0519:52:40
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__CACHE_H__
#define__CACHE_H__
#include<unordered_map>
#include<string>
usingnamespacestd;
namespacewd
{
classCache
{
public:
voidaddElement(string,string);//增加缓存信息
voidreadFromFile(string);//从文件中读取信息
voidwriteToFile(string);//将信息写入文件中
voidupdate(constCache&);//更新缓存消息
boolfind(stringquerry);//从数据库中找寻信息
string&operator[](stringkey);
private:
unordered_map<string,string>_hashTable;//采用hashTable进行缓存
};
};
#endif
///=======================================
///File:Cache.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0520:01:25
///Dream:Don'tforgetyourdreams!
///======================================
#include"Cache.h"
#include<fstream>
#include<utility>
#include<iostream>
usingnamespacestd;
usingnamespacewd;
voidCache::addElement(stringquerry,stringresult)
{
_hashTable[querry]=result;
}
voidCache::readFromFile(stringfilePath)
{
ifstreamifs(filePath);
if(!ifs){
cout<<"Cache::readreadFromFilefileopenerror!"<<endl;
return;
}
stringquerry,result;
while(ifs>>querry,!ifs.eof())
{
ifs>>result;
_hashTable[querry]=result;
}
}
#if0
voidCache::writeToFile(stringfilePath)
{
ofstreamofs(filePath);
if(!ofs){
cout<<""<<endl;
return;
}
for(auto&mypair:_hashTable)
{
ofs<<mypair.first<<"";
ofs<<mypair.second<<endl;
}
}
voidCache::update(constCache&cache)
{
for(auto&mypair:cache._hashTable)
{
autocit=_hashTable.find(mypair.first);
if(cit==_hashTable.end())
{
_hashTable.insert(std::move(mypair));
}
}
}
#endif
voidCache::writeToFile(stringfilePath)
{
ofstreamofs(filePath);
if(!ofs){
cout<<"filewriteerror!"<<endl;
return;
}
for(auto&mypair:_hashTable)
{
ofs<<mypair.first<<"";
ofs<<mypair.second<<endl;
}
}
voidCache::update(constCache&cache)
{
for(auto&mypair:cache._hashTable)
{
autocit=_hashTable.find(mypair.first);
if(cit==_hashTable.end())
{
_hashTable.insert(std::move(mypair));
}
}
}
boolCache::find(stringquerry)
{
autocit=_hashTable.find(querry);
if(cit==_hashTable.end())
returnfalse;
returntrue;
}
string&Cache::operator[](stringkey)
{
return_hashTable[key];
}
#if0
intmain()
{
cout<<"cacheiscorrect!"<<endl;
}
#endif
==CacheManger:==
///=======================================
///File:CacheManger.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0520:51:09
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__CACHEMANGER_H__
#define__CACHEMANGER_H__
#include"Cache.h"
#include<vector>
#defineTHREADNUM4//线程数目设置为4个,可自定义
usingstd::vector;
namespacewd
{
classCacheManger
{
public:
CacheManger(stringfilePath);
voidinit(string);//创建缓存
Cache&getCache(size_t);//获取某个缓存
voidperiodicUpdate();//定时更新所有缓存
private:
string_cacheFilePath;
vector<Cache>_cacheList;
};
};
#endif
///=======================================
///File:CacheManger.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0520:56:50
///Dream:Don'tforgetyourdreams!
///======================================
#include"CacheManger.h"
#include<iostream>
#include<fstream>
#include<utility>
#include<iostream>
usingnamespacestd;
usingnamespacewd;
CacheManger::CacheManger(stringcacheFilePath)
{
init(cacheFilePath);
}
voidCacheManger::init(stringcacheFilePath)
{
_cacheFilePath=cacheFilePath;
_cacheList.reserve(THREADNUM);
Cachetmp;
tmp.readFromFile(_cacheFilePath);
for(size_ti=0;i!=THREADNUM;++i)
{
_cacheList.push_back(std::move(tmp));
}
}
Cache&CacheManger::getCache(size_tnumber)
{
return_cacheList[number];
}
voidCacheManger::periodicUpdate()
{
autocit=_cacheList.begin();
CachelastWrite=*(cit++);
for(;cit<_cacheList.end();++cit)
{
lastWrite.update(*cit);
}
for(cit=_cacheList.begin()+1;cit!=_cacheList.end();++cit)
{
(*cit).update(lastWrite);
}
lastWrite.writeToFile(_cacheFilePath);
}
==EpollPoller:==
///=======================================
///File:EpollPoller.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0611:03:36
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__WD_EPOLLPOLLER_H__
#define__WD_EPOLLPOLLER_H__
#include"TcpConnection.h"
#include"Noncopyable.h"
#include"MutexLock.h"
#include<sys/epoll.h>
#include<vector>
#include<map>
#include<functional>
namespacewd
{
classAcceptor;
classEpollPoller
:Noncopyable
{
public:
typedefTcpConnection::TcpConnectionCallbackEpollCallback;
typedefstd::function<void()>Functor;
EpollPoller(Acceptor&acceptor);
~EpollPoller();
voidloop();
voidunloop();
voidrunInLoop(constFunctor&&cb);
voiddoPendingFunctors();
voidwakeup();
voidsetConnectionCallback(EpollCallbackcb);
voidsetMessageCallback(EpollCallbackcb);
voidsetCloseCallback(EpollCallbackcb);
private:
voidwaitEpollfd();
voidhandleConnection();
voidhandleMessage(intpeerfd);
voidhandleRead();
Acceptor&_acceptor;
int_epollfd;
int_eventfd;
int_listenfd;
bool_isLooping;
MutexLock_mutex;
std::vector<Functor>_pendingFunctors;
typedefstd::vector<structepoll_event>Eventlist;
Eventlist_eventList;
typedefstd::map<int,TcpConnectionPtr>ConnectionMap;
ConnectionMap_connMap;
EpollCallback_onConnectionCb;
EpollCallback_onMessageCb;
EpollCallback_onCloseCb;
};
}
#endif
///=======================================
///File:EpollPoller.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0715:42:54
///Dream:Don'tforgetyourdreams!
///======================================
#include"EpollPoller.h"
#include"SocketUtil.h"
#include"Acceptor.h"
#include<assert.h>
#include<iostream>
usingnamespacestd;
namespacewd
{
EpollPoller::EpollPoller(Acceptor&acceptor)
:_acceptor(acceptor)
,_epollfd(createEpollFd())
,_eventfd(createEventFd())
,_listenfd(_acceptor.fd())
,_isLooping(false)
,_eventList(1024)
{
addEpollFdRead(_epollfd,_listenfd);
addEpollFdRead(_epollfd,_eventfd);
}
EpollPoller::~EpollPoller()
{
::close(_epollfd);
}
voidEpollPoller::loop()
{
_isLooping=true;
while(_isLooping)
{
waitEpollfd();
}
}
voidEpollPoller::unloop()
{
if(_isLooping)
_isLooping=false;
}
voidEpollPoller::setConnectionCallback(EpollCallbackcb)
{
_onConnectionCb=cb;
}
voidEpollPoller::setMessageCallback(EpollCallbackcb)
{
_onMessageCb=cb;
}
voidEpollPoller::setCloseCallback(EpollCallbackcb)
{
_onCloseCb=cb;
}
voidEpollPoller::waitEpollfd()
{
intnready;
do
{
nready=::epoll_wait(_epollfd,&(*_eventList.begin()),_eventList.size(),10000);
}while(-1==nready&&errno==EINTR);
if(-1==nready){
perror("epollwaiterror!");
exit(EXIT_FAILURE);
}elseif(0==nready){
cout<<"epoll_waittimeout!"<<endl;
}else{//扩容
if(nready==static_cast<int>(_eventList.size())){
_eventList.resize(_eventList.size()*2);
}
for(intidx=0;idx!=nready;++idx)//正宗罗老师循环体(TwT)
{
if(_eventList[idx].data.fd==_listenfd)
{
if(_eventList[idx].events&EPOLLIN)
{
handleConnection();
}
}elseif(_eventList[idx].data.fd==_eventfd){
handleRead();
cout<<">>doPendingFunctors()"<<endl;
doPendingFunctors();
}else{
if(_eventList[idx].events&EPOLLIN){
handleMessage(_eventList[idx].data.fd);
}
}
}
}
}
voidEpollPoller::handleConnection()
{
intpeerfd=_acceptor.accept();
addEpollFdRead(_epollfd,peerfd);
TcpConnectionPtrconn(newTcpConnection(peerfd,this));
conn->setConnectionCallback(_onConnectionCb);
conn->setMessageCallback(_onMessageCb);
conn->setCloseCallback(_onCloseCb);
std::pair<ConnectionMap::iterator,bool>ret;
ret=_connMap.insert(std::make_pair(peerfd,conn));
assert(ret.second==true);
(void)ret;
conn->handleConnectionCallback();
}
voidEpollPoller::handleMessage(intpeerfd)
{
boolisClosed=isConnectionClosed(peerfd);
ConnectionMap::iteratorit=_connMap.find(peerfd);
assert(it!=_connMap.end());
if(isClosed)
{
it->second->handleCloseCallback();
delEpollReadFd(_epollfd,peerfd);
_connMap.erase(it);
}else{
it->second->handleMessageCallback();
}
}
voidEpollPoller::runInLoop(constFunctor&&cb)//在计算线程中执行
{
MutexLockGuardmlg(_mutex);
_pendingFunctors.push_back(std::move(cb));
wakeup();
}
voidEpollPoller::doPendingFunctors()
{
std::vector<Functor>tmp;
{
MutexLockGuardmlg(_mutex);
tmp.swap(_pendingFunctors);
}
for(auto&functor:tmp)
{
functor();
}
}
voidEpollPoller::handleRead()
{
uint64_thowmany;
intret=::read(_eventfd,&howmany,sizeof(howmany));
if(ret!=sizeof(howmany))
{
perror("readerror!");
}
}
voidEpollPoller::wakeup()
{
uint64_tone=1;
intret=::write(_eventfd,&one,sizeof(one));
if(ret!=sizeof(one))
{
perror("writeerror!");
}
}
}
==InetAddress:==
///=======================================
///File:InetAddress.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0521:55:19
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__WD_INETADDRESS_H__
#define__WD_INETADDRESS_H__
#include<netinet/in.h>
#include<string>
namespacewd
{
classInetAddress
{
public:
InetAddress(shortport);
InetAddress(constchar*pIp,shortport);
InetAddress(conststructsockaddr_in&addr);
std::stringip()const;
unsignedshortport()const;
conststructsockaddr_in*getSockAddrPtr()const;
private:
structsockaddr_in_addr;
};
}
#endif
///=======================================
///File:InetAddress.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0720:55:18
///Dream:Don'tforgetyourdreams!
///======================================
#include"InetAddress.h"
#include<stdio.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<string.h>
namespacewd
{
InetAddress::InetAddress(shortport)
{
::memset(&_addr,0,sizeof(_addr));
_addr.sin_family=AF_INET;
_addr.sin_port=htons(port);
_addr.sin_addr.s_addr=INADDR_ANY;
}
InetAddress::InetAddress(constchar*pIp,shortport)
{
::memset(&_addr,0,sizeof(_addr));
_addr.sin_family=AF_INET;
_addr.sin_port=htons(port);
_addr.sin_addr.s_addr=inet_addr(pIp);
}
InetAddress::InetAddress(conststructsockaddr_in&addr)
:_addr(addr)
{}
conststructsockaddr_in*InetAddress::getSockAddrPtr()const
{
return&_addr;
}
std::stringInetAddress::ip()const
{
returnstd::string(inet_ntoa(_addr.sin_addr));
}
unsignedshortInetAddress::port()const
{
returnntohs(_addr.sin_port);
}
}
==MutexLock:==
#ifndef__WD_MUTEXLOCK_H__
#define__WD_MUTEXLOCK_H__
#include"Noncopyable.h"
#include<pthread.h>
namespacewd
{
classMutexLock
:Noncopyable
{
public:
MutexLock()
{pthread_mutex_init(&_mutex,NULL);}
~MutexLock()
{pthread_mutex_destroy(&_mutex);}
voidlock()
{pthread_mutex_lock(&_mutex);}
voidunlock()
{pthread_mutex_unlock(&_mutex);}
pthread_mutex_t*getMutexLockPtr()
{return&_mutex;}
private:
pthread_mutex_t_mutex;
};
classMutexLockGuard//C++之父BS提出的RAII
{
public:
MutexLockGuard(MutexLock&mutex)
:_mutex(mutex)
{
_mutex.lock();
}
~MutexLockGuard()
{
_mutex.unlock();
}
private:
MutexLock&_mutex;
};
}
#endif
==Mydict:==
///=======================================
///File:Mydict.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0611:12:19
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__MYDICT_H__
#define__MYDICT_H__
#include<string>
#include<vector>
#include<map>
#include<utility>
#include<set>
#include<fstream>
#include<iostream>
#include<sstream>
usingnamespacestd;
namespacewd
{
structMyResult
{
string_word;
int_iFreq;//词频
int_iDist;//最小编辑距离
};
classMydict
{
public:
Mydict(conststringdictDir,conststringindexDir)
{
ifstreamifs1(dictDir),ifs2(indexDir);
if(!ifs1||!ifs2)
cout<<"Mydictopenfileerror!"<<endl;
stringkey;
intvalue;
ifs1>>value;
_dict.push_back(std::make_pair(string(""),value));
ifs1>>value;
_dict.push_back(std::make_pair(string(""),value));
while(ifs1>>key)
{
ifs1>>value;
_dict.push_back(std::make_pair(key,value));
}
stringline;
while(std::getline(ifs2,line))
{
istringstreamiss(line);
stringikey;
intivalue;
iss>>ikey;
set<int>tmp;
while(iss>>ivalue)
{
tmp.insert(ivalue);
}
_index.insert(std::make_pair(ikey,tmp));
}
}
vector<pair<string,int>>&getDict(){return_dict;}
map<string,set<int>>&getIndexTable(){return_index;}
private:
vector<pair<string,int>>_dict;
map<string,set<int>>_index;
};
}
#endif
==MyTask:==
///=======================================
///File:MyTask.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0621:04:54
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__MYTASK_H__
#define__MYTASK_H__
#include"TcpConnection.h"
#include"ConFiguration.h"
#include"Mydict.h"
#include"Cache.h"
#include<string>
#include<queue>
usingnamespacestd;
classMyCompare
{
public:
booloperator()(constwd::MyResult&lhs,constwd::MyResult&rhs)
{
if(lhs._iDist!=rhs._iDist)
returnlhs._iDist<rhs._iDist;
else
returnlhs._iFreq>rhs._iFreq;
}
private:
};
usingCharacter=string;
classMyTask
{
public:
MyTask(conststring&querry,constwd::TcpConnectionPtrconn)
:_querry(std::move(querry))
,_conn(conn)
{}
voidexecute();
private:
voidqueryIndexTable();//查询索引(四个索引)
voidstatistic(set<int>&iset);//计算
intdistance(conststring&rhs);//计算最小编辑距离
boolresponse(wd::Cache&cache);//响应客户端的请求
vector<Character>getOneCharacter(conststring&word);//获取字符数组
string_querry;
wd::TcpConnectionPtr_conn;
priority_queue<wd::MyResult,vector<wd::MyResult>,MyCompare>_resultQue;
};
#endif
///=======================================
///File:MyTask.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0722:47:19
///Dream:Don'tforgetyourdreams!
///======================================
#include"MyTask.h"
#include"ConFiguration.h"
#include"Mydict.h"
#include"CacheManger.h"
#include"json/json.h"
#include<string.h>
#include<algorithm>
extern__threadintt_number;
boolMyTask::response(wd::Cache&cache)
{
if(cache.find(_querry))
{
_conn->sendInLoop(cache[_querry]);
returntrue;
}
returnfalse;
}
intMyTask::distance(conststring&rhs)
{
vector<Character>querryCharacter=getOneCharacter(_querry);
vector<Character>indexCharacter=getOneCharacter(rhs);
intlen1,len2;
len1=querryCharacter.size();
len2=indexCharacter.size();
intedit[len1+1][len2+1];
inti,j;
for(i=0;i<=len1;++i){
for(j=0;j<=len2;++j){
edit[i][j]=0;
}
}
for(i=0;i<len1;++i){
edit[i][0]=i;
}
for(j=0;j<=len2;++j){
edit[0][j]=j;
}
for(i=1;i<len1;++i){
for(j=1;j<=len2;++j){
intcost=((querryCharacter[i-1]==indexCharacter[j-1])?0:1);
intdeletion=edit[i-1][j]+1;
intinsertion=edit[i][j-1]+1;
intsubstitution=edit[i-1][j-1]+cost;
edit[i][j]=std::min(deletion,std::min(insertion,substitution));
}
}
returnedit[len1][len2];
}
voidMyTask::statistic(set<int>&iset)
{
vector<pair<string,int>>dict=(Singleton<wd::Mydict>::getInstance(Singleton<wd::Configuration>::getInstance(CONFPATH)->getDictDir(),
Singleton<wd::Configuration>::getInstance(CONFPATH)->getIndexDir()))->getDict();
for(auto&idx:iset)
{
stringkey=dict[idx].first;
intiDist=distance(key);
if(iDist<=3)
{
wd::MyResultres;
res._word=key;
res._iDist=iDist;
res._iFreq=dict[idx].second;
_resultQue.push(res);
}
}
}
vector<Character>MyTask::getOneCharacter(conststring&word)
{
autocit=word.begin();
vector<Character>ret;
while(cit<word.end())
{
if(224==(*cit&224)){
CharacteroneCharacter;
oneCharacter.append(cit,cit+3);
ret.push_back(oneCharacter);
cit=cit+3;
}elseif(240==(*cit&240)){
CharacteroneCharacter;
oneCharacter.append(cit,cit+4);
ret.push_back(oneCharacter);
cit=cit+4;
}else{
CharacteroneCharacter(1,*cit);
ret.push_back(oneCharacter);
cit++;
}
}
returnret;
}
voidMyTask::queryIndexTable()
{
map<string,set<int>>index=(Singleton<wd::Mydict>::getInstance(Singleton<wd::Configuration>::getInstance(CONFPATH)->getDictDir(),
Singleton<wd::Configuration>::getInstance(CONFPATH)->getIndexDir()))->getIndexTable();
vector<Character>oneCharacter=getOneCharacter(_querry);
set<int>allRally;
for(automyCharacter:oneCharacter)
{
autocit=index.find(myCharacter);
if(cit!=index.end())
{
for(auto&idx:cit->second)
allRally.insert(idx);
}
}
statistic(allRally);
}
voidMyTask::execute()
{
wd::Cache&mycache=(Singleton<wd::CacheManger>::getInstance(Singleton<wd::Configuration>::getInstance(CONFPATH)->getCache()))->getCache(t_number);
if(response(mycache))
return;
else{
queryIndexTable();
Json::FastWriterwriterinfo;
Json::ValuearrayObj;
while(!_resultQue.empty())
{
Json::Valuenew_item;
new_item[""]=_resultQue.top()._word;
_resultQue.pop();
arrayObj.append(new_item);
}
stringstrEmail=writerinfo.write(arrayObj);
mycache.addElement(_querry,strEmail);
_conn->sendInLoop(strEmail);
}
}
==Noncopyable:==
#ifndef__WD_NONCOPYABLE_H__
#define__WD_NONCOPYABLE_H__
namespacewd
{
classNoncopyable
{
protected:
Noncopyable(){}
~Noncopyable(){}
private:
Noncopyable(constNoncopyable&);
Noncopyable&operator=(constNoncopyable&);
};
}
#endif
==Socket:==
///=======================================
///File:Socket.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0521:46:26
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__WD_SOCKET_H__
#define__WD_SOCKET_H__
#include"Noncopyable.h"
namespacewd
{
classInetAddress;
classSocket
:Noncopyable
{
public:
Socket(intsocket);
Socket();
~Socket();
voidshutdownWrite();
intfd()const{return_sockfd;}
voidnonblock();
staticInetAddressgetLocalAddr(intsocketfd);
staticInetAddressgetPeerAddr(intsockfd);
private:
int_sockfd;
};
}
#endif
///=======================================
///File:Socket.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0720:38:20
///Dream:Don'tforgetyourdreams!
///======================================
#include"Socket.h"
#include"SocketUtil.h"
#include"InetAddress.h"
namespacewd
{
Socket::Socket(intsockfd)
:_sockfd(sockfd)
{}
Socket::Socket()
:_sockfd(createSocketFd())
{}
Socket::~Socket()
{
::close(_sockfd);
}
voidSocket::nonblock()
{
setNonblock(_sockfd);
}
voidSocket::shutdownWrite()
{
if(-1==::shutdown(_sockfd,SHUT_WR)){
perror("shutdownwriteerror!");
}
}
InetAddressSocket::getLocalAddr(intsockfd)
{
structsockaddr_inaddr;
socklen_tlen=sizeof(sockaddr_in);
if(-1==::getsockname(sockfd,(structsockaddr*)&addr,&len)){
perror("getsocknameerror!");
}
returnInetAddress(addr);
}
InetAddressSocket::getPeerAddr(intsockfd)
{
structsockaddr_inaddr;
socklen_tlen=sizeof(sockaddr_in);
if(-1==::getpeername(sockfd,(structsockaddr*)&addr,&len)){
perror("getpeernameerror!");
}
returnInetAddress(addr);
}
}
==SocketIO:==
///=======================================
///File:SocketIO.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0617:10:23
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__SOCKETIO_H__
#define__SOCKETIO_H__
#include<stdio.h>
namespacewd
{
classSocketIO
{
public:
SocketIO(intsockfd);
size_treadn(char*buf,size_tcount);
size_twriten(constchar*buf,size_tcount);
size_treadline(char*buf,size_tmax_len);
private:
size_trecv_peek(char*buf,size_tcount);
int_sockfd;
};
}
#endif
///=======================================
///File:SocketIO.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0721:56:34
///Dream:Don'tforgetyourdreams!
///======================================
#include"SocketIO.h"
#include"SocketUtil.h"
namespacewd
{
SocketIO::SocketIO(intsockfd)
:_sockfd(sockfd)
{}
size_tSocketIO::readn(char*buf,size_tcount)
{
size_tnleft=count;
char*pbuf=buf;
while(nleft>0)
{
intnread=::read(_sockfd,pbuf,nleft);
if(-1==nread)
{
if(errno==EINTR)
continue;
returnEXIT_FAILURE;
}elseif(0==nread){
break;
}
pbuf=pbuf+nread;
nleft=nleft-nread;
}
return(count-nleft);
}
size_tSocketIO::writen(constchar*buf,size_tcount)
{
size_tnleft=count;
constchar*pbuf=buf;
while(nleft>0)
{
intnwrite=::write(_sockfd,pbuf,nleft);
if(-1==nwrite)
{
if(errno==EINTR)
continue;
returnEXIT_FAILURE;
}
nleft=nleft-nwrite;
pbuf=pbuf+nwrite;
}
return(count-nleft);
}
size_tSocketIO::recv_peek(char*buf,size_tcount)
{
intnread;
do{
nread=::recv(_sockfd,buf,count,MSG_PEEK);
}while(-1==nread&&errno==EINTR);
returnnread;
}
size_tSocketIO::readline(char*buf,size_tmaxlen)
{
size_tnleft=maxlen-1;
char*pbuf=buf;
size_ttotal=0;
while(nleft>0)
{
size_tnread=recv_peek(pbuf,nleft);
if(nread<=0)
returnnread;
for(size_tidx=0;idx!=nread;++idx){//检查换行符/n
if(pbuf[idx]=='\n'){
size_tnsize=idx+1;
if(readn(pbuf,nsize)!=nsize)
returnEXIT_FAILURE;
pbuf+=nsize;
total+=nsize;
*pbuf=0;
returntotal;
}
}
if(readn(pbuf,nread)!=nread)
returnEXIT_FAILURE;
pbuf+=nread;
nleft-=nread;
total+=nread;
}
*pbuf=0;
returnmaxlen-1;
}
}
==SockUtil(根据陈硕编写的LINUX书上分开头文件)==
///=======================================
///File:SocktUtil.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0522:01:30
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__WD_SOCKERUTIL_H__
#define__WD_SOCKERUTIL_H__
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/eventfd.h>
#include<sys/epoll.h>
namespacewd
{
inlineintcreateSocketFd()
{
intfd=::socket(AF_INET,SOCK_STREAM,0);
if(-1==fd)
{
perror("socketcreateerror!");
}
returnfd;
}
inlinevoidsetNonblock(intfd)
{
intflags=::fcntl(fd,F_GETFL,0);
flags|=O_NONBLOCK;
::fcntl(fd,F_SETFL,flags);
}
inlineintcreateEpollFd()
{
intefd=::epoll_create1(0);
if(-1==efd)
{
perror("epollcreate1error!");
exit(EXIT_FAILURE);
}
returnefd;
}
inlineintcreateEventFd()
{
intevtfd=::eventfd(0,EFD_NONBLOCK|EFD_CLOEXEC);
if(-1==evtfd)
{
perror("eventfdcreateerror!");
}
returnevtfd;
}
inlinevoidaddEpollFdRead(intefd,intfd)
{
structepoll_eventev;
ev.data.fd=fd;
ev.events=EPOLLIN;
intret=epoll_ctl(efd,EPOLL_CTL_ADD,fd,&ev);
if(-1==ret)
{
perror("epollctladderror!");
exit(EXIT_FAILURE);
}
}
inlinevoiddelEpollReadFd(intefd,intfd)
{
structepoll_eventev;
ev.data.fd=fd;
intret=epoll_ctl(efd,EPOLL_CTL_DEL,fd,&ev);
if(-1==ret)
{
perror("epollctldeleteerror!");
exit(EXIT_FAILURE);
}
}
inlinesize_trecvPeek(intsockfd,void*buf,size_tlen)
{
intnread;
do{
nread=::recv(sockfd,buf,len,MSG_PEEK);
}while(nread==-1&&errno==EINTR);
returnnread;
}
inlineboolisConnectionClosed(intsockfd)
{
charbuf[1024];
intnread=recvPeek(sockfd,buf,sizeof(buf));
if(-1==nread)
{
perror("recvPeekerror!");
returntrue;
}
return(0==nread);
}
}
#endif
==SpellCorrrectSever:==
///=======================================
///File:SpellCorrectServer.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0620:41:13
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__SPELLCORRECTSERVER_H__
#define__SPELLCORRECTSERVER_H__
#include"TcpServer.h"
#include"Threadpool.h"
usingnamespacewd;
namespacewd
{
classSpellCorrectServer
{
public:
SpellCorrectServer(conststring&ip
,unsignedshortport
,size_tthreadNUM
,size_tqueSize);
voidstart();
private:
voidonConnection(constTcpConnectionPtr&);
voidonMessage(constTcpConnectionPtr&);
voidonClose(constTcpConnectionPtr&);
TcpServer_tcpserver;
Threadpool_threadpoll;
};
};
#endif
///=======================================
///File:SpellCorrectServer.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0721:20:41
///Dream:Don'tforgetyourdreams!
///======================================
#include"SpellCorrectServer.h"
#include"MyTask.h"
#include<stdio.h>
#include<iostream>
#include<string>
#include<utility>
#include<functional>
usingnamespacestd;
voidSpellCorrectServer::onConnection(constwd::TcpConnectionPtr&conn)
{
cout<<conn->toString()<<endl;
conn->send("hello,welcometoWTPChatServer.\r\n");
}
voidSpellCorrectServer::onMessage(constwd::TcpConnectionPtr&conn)
{
strings(conn->receive());
MyTasktask(s,conn);
_threadpoll.addTask(std::bind(&MyTask::execute,&task));
cout<<">addtasktothreadpool"<<endl;
}
voidSpellCorrectServer::onClose(constwd::TcpConnectionPtr&conn)
{
::printf("%sclose\n",conn->toString().c_str());
}
SpellCorrectServer::SpellCorrectServer(conststring&ip
,unsignedshortport
,size_tthreadNUM
,size_tqueSize)
:_tcpserver(ip,port)
,_threadpoll(threadNUM,queSize)
{}
voidSpellCorrectServer::start()
{
_threadpoll.start();
_tcpserver.setConnectionCallback(std::bind(&SpellCorrectServer::onConnection,this,std::placeholders::_1));
_tcpserver.setMessageCallback(std::bind(&SpellCorrectServer::onMessage,this,std::placeholders::_1));
_tcpserver.setCloseCallback(std::bind(&SpellCorrectServer::onClose,this,std::placeholders::_1));
_tcpserver.start();
}
==TaskQue:==
#ifndef__WD_TASKQUEUE_H__
#define__WD_TASKQUEUE_H__
#include"MutexLock.h"
#include"Condition.h"
#include<queue>
#include<functional>
namespacewd
{
typedefstd::function<void()>Task;
classTaskQueue
{
public:
TaskQueue(size_tqueSize)
:_queSize(queSize)
,_mutex()
,_notFull(_mutex)
,_notEmpty(_mutex)
,_flag(true)
{}
voidpush(Task&&task);
Taskpop();
boolempty()const
{
return_que.size()==0;
}
boolfull()const
{return_que.size()==_queSize;}
voidwakeup()
{
if(_flag)
_flag=false;
_notEmpty.notifyAll();
}
private:
size_t_queSize;
std::queue<Task>_que;
MutexLock_mutex;
Condition_notFull;
Condition_notEmpty;
bool_flag;
};
}
#endif
#include"TaskQueue.h"
usingnamespacewd;
//生产者所在的线程
voidTaskQueue::push(Task&&task)
{
MutexLockGuardautoLock(_mutex);
while(full())
{
_notFull.wait();
}
_que.push(std::move(task));
_notEmpty.notify();
}
//消费者所在线程
TaskTaskQueue::pop()
{
MutexLockGuardautoLock(_mutex);
while(_flag&&empty())
{
_notEmpty.wait();
}
if(_flag){
Tasktask=_que.front();
_que.pop();
_notFull.notify();
returntask;
}else{
returnNULL;
}
}
#if0
TaskTaskQueue::pop()
{
MutexLockGuardautoLock(_mutex);
while(_flag&&empty())
{
_notEmpty.wait();
}
if(_flag){
Tasktask=_que.front();
_que.pop();
_notFull.notify();
returntask;
}else{
returnNULL;
}
}
#endif
==TcpConnection:==
///=======================================
///File:TcpConnection.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0617:15:33
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__WD_TCPCONNECTION_H__
#define__WD_TCPCONNECTION_H__
#include"Noncopyable.h"
#include"InetAddress.h"
#include"Socket.h"
#include"SocketIO.h"
#include<string>
#include<memory>
#include<functional>
namespacewd
{
classEpollPoller;
classTcpConnection;
typedefstd::shared_ptr<TcpConnection>TcpConnectionPtr;
classTcpConnection
:Noncopyable
,publicstd::enable_shared_from_this<TcpConnection>
{
public:
typedefstd::function<void(constTcpConnectionPtr&)>TcpConnectionCallback;
TcpConnection(intsockfd,EpollPoller*loop);
~TcpConnection();
std::stringreceive();
voidsend(conststd::string&msg);
voidsendInLoop(conststd::string&msg);
voidshutdown();
std::stringtoString();
voidsetConnectionCallback(TcpConnectionCallbackcb);
voidsetMessageCallback(TcpConnectionCallbackcb);
voidsetCloseCallback(TcpConnectionCallbackcb);
voidhandleConnectionCallback();
voidhandleMessageCallback();
voidhandleCloseCallback();
private:
Socket_sockfd;
SocketIO_sockIO;
constInetAddress_localAddr;
constInetAddress_peerAddr;
bool_isShutdownWrite;
EpollPoller*_loop;
TcpConnectionCallback_onConnectionCb;
TcpConnectionCallback_onMessageCb;
TcpConnectionCallback_onCloseCb;
};
}
#endif
///=======================================
///File:TcpConnection.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0722:22:22
///Dream:Don'tforgetyourdreams!
///======================================
#include"TcpConnection.h"
#include"EpollPoller.h"
#include<string.h>
#include<stdio.h>
namespacewd
{
TcpConnection::TcpConnection(intsockfd,EpollPoller*loop)
:_sockfd(sockfd)
,_sockIO(sockfd)
,_localAddr(wd::Socket::getLocalAddr(sockfd))
,_peerAddr(wd::Socket::getPeerAddr(sockfd))
,_isShutdownWrite(false)
,_loop(loop)
{_sockfd.nonblock();}
TcpConnection::~TcpConnection()
{
if(!_isShutdownWrite)
{
_isShutdownWrite=true;
shutdown();
}
printf("~TcpConnection()\n");
}
std::stringTcpConnection::receive()
{
charbuf[65536];
memset(buf,0,sizeof(buf));
size_tret=_sockIO.readline(buf,sizeof(buf));
if(0==ret){
returnstd::string();
}else{
returnstd::string(buf);
}
}
voidTcpConnection::send(conststd::string&msg)
{
size_tlen=msg.size();
_sockIO.writen((constchar*)&len,sizeof(int));
_sockIO.writen(msg.c_str(),len);
}
voidTcpConnection::shutdown()
{
if(!_isShutdownWrite)
_sockfd.shutdownWrite();
_isShutdownWrite=true;
}
std::stringTcpConnection::toString()
{
charstr[100];
snprintf(str,sizeof(str),"%s:%d->%s:%d"
,_localAddr.ip().c_str()
,_localAddr.port()
,_peerAddr.ip().c_str()
,_peerAddr.port());
returnstd::string(str);
}
voidTcpConnection::setConnectionCallback(TcpConnectionCallbackcb)
{
_onConnectionCb=cb;
}
voidTcpConnection::setMessageCallback(TcpConnectionCallbackcb)
{
_onMessageCb=cb;
}
voidTcpConnection::setCloseCallback(TcpConnectionCallbackcb)
{
_onCloseCb=cb;
}
voidTcpConnection::handleConnectionCallback()
{
if(_onConnectionCb){
_onConnectionCb(shared_from_this());
}
}
voidTcpConnection::handleMessageCallback()
{
if(_onMessageCb){
_onMessageCb(shared_from_this());
}
}
voidTcpConnection::handleCloseCallback()
{
if(_onCloseCb){
_onCloseCb(shared_from_this());
}
}
voidTcpConnection::sendInLoop(conststd::string&msg)
{
_loop->runInLoop(std::bind(&TcpConnection::send,this,msg));
}
}
==TcpServer:==
///=======================================
///File:TcpServer.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0620:15:21
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__WD_TCPSERVER_H__
#define__WD_TCPSERVER_H__
#include"Acceptor.h"
#include"EpollPoller.h"
#include<string>
usingstd::string;
namespacewd
{
classTcpServer
{
public:
typedefEpollPoller::EpollCallbackTcpServerCallback;
TcpServer(conststring&ip,unsignedshortport);
TcpServer(unsignedshortport);
voidstart();
voidstop();
voidsetConnectionCallback(TcpServerCallbackcb);
voidsetMessageCallback(TcpServerCallbackcb);
voidsetCloseCallback(TcpServerCallbackcb);
private:
Acceptor_acceptor;
EpollPoller_poller;
TcpServerCallback_connectionCallback;
TcpServerCallback_messageCallback;
TcpServerCallback_closeCallback;
};
}
#endif
///=======================================
///File:TcpServer.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0719:59:37
///Dream:Don'tforgetyourdreams!
///======================================
#include"TcpServer.h"
#include"InetAddress.h"
#include"SocketUtil.h"
#include<iostream>
usingnamespacestd;
namespacewd
{
TcpServer::TcpServer(conststring&ip,unsignedshortport)
:_acceptor(createSocketFd(),InetAddress(ip.c_str(),port))
,_poller(_acceptor)
{}
voidTcpServer::start()
{
_acceptor.ready();
_poller.setConnectionCallback(_connectionCallback);
_poller.setMessageCallback(_messageCallback);
_poller.setCloseCallback(_closeCallback);
_poller.loop();
}
voidTcpServer::stop()
{
_poller.unloop();
}
voidTcpServer::setConnectionCallback(TcpServerCallbackcb)
{_connectionCallback=cb;}
voidTcpServer::setMessageCallback(TcpServerCallbackcb)
{_messageCallback=cb;}
voidTcpServer::setCloseCallback(TcpServerCallbackcb)
{_closeCallback=cb;}
}
==Thread:==
#ifndef__WD_THREAD_H__
#define__WD_THREAD_H__
#include"Noncopyable.h"
#include<pthread.h>
#include<functional>
usingstd::function;
namespacewd
{
classThread;
structThreadPtr
{
int_number;
Thread*_pthread;
};
classThread
:Noncopyable
{
usingThreadCallback=function<void()>;
public:
Thread(ThreadCallback&&cb);
~Thread();
voidstart(intnumber);
voidjoin();
boolisRunning()const{return_isRunning;}
private:
staticvoid*threadFunc(void*);
pthread_t_pthid;
bool_isRunning;
ThreadCallback_cb;
};
}
#endif
#include"Thread.h"
#include<iostream>
usingnamespacestd;
usingnamespacewd;
__threadintt_number;//将线程编号作为线程存储的标记
Thread::Thread(ThreadCallback&&cb)//这里的右值引用本身取决于是否有名字
:_pthid(0)
,_isRunning(false)
,_cb(std::move(cb))
{
cout<<"Thread(cb)"<<endl;
}
voidThread::start(intnumber)
{
ThreadPtr*threadPtr=newThreadPtr();
threadPtr->_number=number;
threadPtr->_pthread=this;
pthread_create(&_pthid,NULL,threadFunc,threadPtr);
_isRunning=true;
}
void*Thread::threadFunc(void*arg)
{//应用了线程存储
ThreadPtr*threadPtr=static_cast<ThreadPtr*>(arg);
Thread*pthread=threadPtr->_pthread;
t_number=threadPtr->_number;
if(pthread)
pthread->_cb();//线程开始工作!
deletethreadPtr;
//Thread*pthread=threadPtr->_pthread;
returnNULL;
}
#if0
void*Thread::threadFunc(void*arg)
{
ThreadPtr*threadPtr=static_cast<ThreadPtr*>(arg);
Thread*pthread=threadPtr->_pthread;
t_number=threadPtr->_number;
if(pthread)
pthread->_cb();
deletethreadPtr;
returnNULL;
}
#endif
voidThread::join()
{
pthread_join(_pthid,NULL);
_isRunning=false;
}
Thread::~Thread()
{
if(_isRunning)
{
pthread_detach(_pthid);
_isRunning=false;
}
cout<<"~Thread()"<<endl;
}
==Threadpool:==
#ifndef__WD_THREADPOLL_H__
#define__WD_THREADPOLL_H__
#include"TaskQueue.h"
#include"Thread.h"
#include<vector>
#include<memory>
#include<functional>
usingstd::shared_ptr;
usingstd::vector;
namespacewd
{
classThreadpool
{
public:
usingTask=std::function<void()>;
Threadpool(size_tthreadNum,size_tqueSize)
:_threadNum(threadNum)
,_queSize(queSize)
,_taskQue(_queSize)
,_isExit(false)
{
_threads.reserve(_threadNum);
}
~Threadpool();
voidstart();
voidstop();
voidaddTask(Task&&task);
private:
voidthreadFunc();
TaskgetTask();
size_t_threadNum;
size_t_queSize;
vector<shared_ptr<Thread>>_threads;
TaskQueue_taskQue;
bool_isExit;
};
}
#endif
#include"Threadpool.h"
#include"Thread.h"
#include<unistd.h>
#include<iostream>
usingnamespacestd;
usingnamespacewd;
voidThreadpool::start()
{
for(size_tidx=0;idx<_threadNum;++idx)
{
shared_ptr<Thread>pThread(newThread(std::bind(&Threadpool::threadFunc,this)));
_threads.push_back(std::move(pThread));
}
intnumber=0;
for(auto&pThread:_threads)
{
pThread->start(number);
++number;
}
}
voidThreadpool::stop()//为了线程安全,将stop方法置于主线程中
{
if(!_isExit)
{
while(!_taskQue.empty()){
::sleep(1);
cout<<"Threadpoolsleep1second!"<<endl;
}
_isExit=true;
cout<<"Threadpool->stop:_isExit="<<_isExit<<endl;
_taskQue.wakeup();
for(auto&pthread:_threads){
pthread->join();
}
}
}
Threadpool::~Threadpool()
{
if(!_isExit){
stop();
}
}
voidThreadpool::addTask(Task&&task)
{
_taskQue.push(std::move(task));
}
TaskThreadpool::getTask()
{
return_taskQue.pop();
}
voidThreadpool::threadFunc()
{
while(!_isExit)
{
Tasktask=getTask();
if(task){
task();
}
}
}
==Timer:==
///=======================================
///File:Timer.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0620:00:45
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__WD_TIMER_H__
#define__WD_TIMER_H__
#include<functional>
namespacewd
{
classTimer
{
public:
usingTimerCallback=std::function<void()>;
Timer(intinitailTime,intintervalTime,TimerCallback&&cb);
~Timer();
voidstart();
voidstop();
private:
int_fd;
int_initialTime;
int_intervalTime;
TimerCallback_cb;
bool_isStarted;
intcreateTimerFd();
voidsetTimerfd(intinitialTime,intintervalTime);
voidhandleRead();
};
}
#endif
///=======================================
///File:Timer.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0720:09:14
///Dream:Don'tforgetyourdreams!
///======================================
#include"Timer.h"
#include<unistd.h>
#include<errno.h>
#include<poll.h>
#include<sys/timerfd.h>
#include<iostream>
usingnamespacestd;
usingnamespacewd;
Timer::Timer(intinitialTime,intintervalTime,TimerCallback&&cb)
:_fd(createTimerFd())
,_initialTime(initialTime)
,_intervalTime(intervalTime)
,_cb(std::move(cb))
,_isStarted(false)
{}
voidTimer::start()
{
structpollfdpfd;
pfd.fd=_fd;
pfd.events=POLLIN;
setTimerfd(_initialTime,_intervalTime);//开启定时器
_isStarted=true;
while(_isStarted){
intnready=::poll(&pfd,1,5000);
if(-1==nready&&errno==EINTR){
continue;
}elseif(-1==nready){
perror(">>>pollerror!");
exit(EXIT_FAILURE);
}elseif(0==nready){
cout<<">>>polltimeout!"<<endl;
}else{
if(pfd.revents&POLLIN){
handleRead();//先对定时器进行处理
if(_cb){
_cb();//再去执行回调任务
}
}
}
}
}
voidTimer::stop()
{
setTimerfd(0,0);
if(_isStarted){
_isStarted=false;
}
}
Timer::~Timer()
{
if(_isStarted){
stop();
}
}
intTimer::createTimerFd()
{
intfd=::timerfd_create(CLOCK_REALTIME,0);
if(-1==fd){
perror(">>timerfd_createerror!");
}
returnfd;
}
voidTimer::setTimerfd(intinitialTime,intintervalTime)
{
structitimerspecvalue;
value.it_value.tv_sec=initialTime;
value.it_value.tv_nsec=0;
value.it_interval.tv_sec=intervalTime;
value.it_interval.tv_nsec=0;
intret=::timerfd_settime(_fd,0,&value,NULL);
if(-1==ret){
perror(">>>timerfd_settimeerror!");
}
}
#if0
voidTimer::handleRead()
{
uint64_thowmany;
intret=::read(_fd,&howmany,sizeof(uint64_t));
if(ret!=sizeof(uint64_t)){
perror("read!");
}
}
#endif
voidTimer::handleRead()
{
uint64_thowmany;//为一个64位
intret=::read(_fd,&howmany,sizeof(uint64_t));
if(ret!=sizeof(uint64_t)){
perror(">>>readerror!");
}
}
==TimerThread:==
///=======================================
///File:TimerThread.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0717:12:51
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__WD_TIMERTHREAD_H__
#define__WD_TIMERTHREAD_H__
#include"Timer.h"
#include"Thread.h"
#include<functional>
namespacewd
{
classTimerThread
{
public:
usingTimerCallback=std::function<void()>;
TimerThread(int,int,TimerCallback&&cb);
~TimerThread();
voidstart();
voidstop();
private:
Timer_timer;
Thread_subThread;
bool_isStarted;
};
}//endofnamespacewd
#endif
///=======================================
///File:TimerThread.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0720:09:14
///Dream:Don'tforgetyourdreams!
///======================================
#include"TimerThread.h"
usingnamespacewd;
TimerThread::TimerThread(intinitialTime,intintervalTime,TimerCallback&&cb)
:_timer(initialTime,intervalTime,std::move(cb))
,_subThread(std::bind(&Timer::start,&_timer))
,_isStarted(false)
{}
voidTimerThread::start()
{
_subThread.start(0);
_isStarted=true;
}
voidTimerThread::stop()
{
if(_isStarted){
_timer.stop();
_subThread.join();
_isStarted=false;
}
}
TimerThread::~TimerThread()
{
if(_isStarted)
stop();
}
==main:==
///=======================================
///File:main.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0721:09:32
///Dream:Don'tforgetyourdreams!
///======================================
#include"SpellCorrectServer.h"
#include"ConFiguration.h"
#include"CacheManger.h"
#include"TimerThread.h"
#include<iostream>
#include<functional>
usingnamespacestd;
usingnamespacewd;
intmain()
{
wd::CacheManger*mycacheManger=Singleton<CacheManger>::getInstance(Singleton<Configuration>
::getInstance(CONFPATH)->getCache());
TimerThreadtimer(5,600,std::bind(&CacheManger::periodicUpdate,mycacheManger));
timer.start();
SpellCorrectServermyspell(Singleton<Configuration>::getInstance(CONFPATH)->getIp()
,Singleton<Configuration>::getInstance(CONFPATH)->getPort()
,4
,10);
myspell.start();
return0;
}
小结:(1)已经实现项目需求,中文和英文单词都能查询,经过测试,运行稳定,能输出不少候选词
?(2)仍然存在少量bug,例如偶尔会发生段错误
?(3)由于时间问题,json读出的数据key-value的key值没有打印,用户界面还未来得及优化
?(4)陈硕的《linux多线程服务端编程》使用linux接口(timerfd),没用posix接口(eventfd)
---恢复内容结束---
#我的Spellcorrect开发文档
[TOC]
相关配置文件及准备工作:
我的主要文件夹分为三个:分别为客户端,cppjieba分词库,离线部分及服务器部分
1560856582308
客户端部分:内部为客户端源码及运行程序
1560856552431
cppjieba分词库部分,就不赘述,请自行安装
离线部分:内部有中英文件夹放置索引及词典文件,还有配置文件及分词库,其余为代码
1560857073864
服务器部分:最为重要的配置文件及数据部分,头文件在include,实现文件在src里面
1560857034230
演示效果(中文):
==启动时服务器:==
1560857677039
==客户端连入时时服务器:==
1560857739202
==输入“赵”==
1560858117388
==输入“周杰伦”==
1560858201376
==输入清华大学==
1560858560147
演示效果(英语):
==启动时服务器:==
1560857677039
==客户端连入时时服务器:==
1560857739202
==输入student:==
1560858008297
==输入spell:==
1560858872540
==输入computer:==
1560859162357
代码部分:
离线部分:
img
==Makefile:==
SRCS:=$(wildcard*.cc)
OBJS:=$(patsubst%.cc,%.o,$(SRCS))
CXX:=g++
CXXFLAGS:=-w-g-std=c++11$(addprefix-I,$(INC_DIR))$(LIBS)-Wno-deprecated-I../cppjieba/include/-I../cppjieba/deps
EXE:=./main
$(EXE):$(OBJS)
$(CXX)-o$(EXE)$(OBJS)$(CXXFLAGS)
clean:
rm-rf$(EXE)
rm-rf$(OBJS)
==Configuration:==
///=======================================
///File:Configuration.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-1200:30:39
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__CONFIGURATION_H__
#define__CONFIGURATION_H__
#include"Nocopyable.h"
#include<string>
#include<map>
usingnamespacestd;
classConfiguration
:publicNoncopyable
{
public:
Configuration(conststring&filePath);
stringgetEnglishDir()const{return_englishDir;}
stringgetChineseDir()const{return_chineseDir;}
private:
string_filePath;
string_englishDir;
string_chineseDir;
};
template<typenameT>
classSingleton
{
public:
template<typename...Args>
staticT*getInstance(Args...args)
{
if(!_pInstance)
_pInstance=newT(args...);
return_pInstance;
}
staticvoiddestroy()
{
if(_pInstance)
delete_pInstance;
}
private:
Singleton();
~Singleton();
staticT*_pInstance;
};
template<typenameT>
T*Singleton<T>::_pInstance=NULL;
#endif
1///=======================================
2///File:Configuration.cc
3///Author:wtptorres(1584292712@qq.com)
4///Date:2019-06-1200:30:04
5///Dream:Don'tforgetyourdreams!
6///======================================
7
8
9#include"Configuration.h"
10#include<utility>
11#include<fstream>
12#include<iostream>
13usingnamespacestd;
14
15Configuration::Configuration(conststring&filePath)
16:_filePath(std::move(filePath))
17{
18ifstreamifs(_filePath);
19if(!ifs)
20cout<<"fileopenerror!"<<endl;
21ifs>>_englishDir;
22ifs>>_chineseDir;
23ifs.close();
24}
///=======================================
///File:Nocopyable.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-1200:24:36
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__NOCOPYABLE_H__
#define__NOCOPYABLE_H__
classNoncopyable
{
public:
Noncopyable()=default;
~Noncopyable()=default;
private:
Noncopyable(constNoncopyable&rhs);
Noncopyable&operator=(constNoncopyable&rhs);
};
#endif
==DictProducer:==
///=======================================
///File:DictProducer.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-1216:40:25
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__DICTPRODUCER_H__
#define__DICTPRODUCER_H__
#include"SplitTool.h"
usingnamespacestd;
#include"Nocopyable.h"
#include<memory>
#include<string>
#include<vector>
#include<map>
#include<utility>
classDictProducer
:publicNoncopyable
{
public:
DictProducer(conststring,conststring,conststring&,SplitToolJieba*);
~DictProducer(){}
voidbuild_dict();
voidbuild_cn_dict();
voidstore_dict();
vector<pair<string,int>>&getIndict(){return_indict;}
private:
voidprocessEnglishWord(string&word);
voidprocessChineseWord(string&word);//除去中文的数字
voidconstruct_indict();
string_englishDir;
string_chineseDir;
string_goleFilePath;
vector<string>_englishFiles;
vector<string>_chineseFiles;
map<string,int>_dict;
vector<pair<string,int>>_indict;
shared_ptr<SplitToolJieba>_splitTool;
};
#endif
///=======================================
///File:DictProducer.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-1216:50:46
///Dream:Don'tforgetyourdreams!
///======================================
#include"DictProducer.h"
#include<cctype>
#include<utility>
#include<fstream>
#include<iostream>
#defineFIRSTSIZE10000
usingnamespacestd;
DictProducer::DictProducer(conststringenglishDir,conststringchineseDir,conststring&goleFilePath,SplitToolJieba*splitToolPtr)
:_englishDir(englishDir)
,_chineseDir(chineseDir)
,_goleFilePath(goleFilePath)
{
_splitTool.reset(splitToolPtr);
std::ifstreamifsEnglish(_englishDir);
std::ifstreamifsChinese(_chineseDir);
stringfilePath;
if(!ifsEnglish||!ifsChinese){
cout<<"Dictfileopenerror!"<<endl;
}
while(ifsEnglish>>filePath)
{
_englishFiles.push_back(filePath);
}
while(ifsChinese>>filePath)
{
_chineseFiles.push_back(filePath);
}
_indict.reserve(FIRSTSIZE);
}
voidDictProducer::processEnglishWord(string&word)
{
autocit=word.begin();
for(;cit!=word.end();++cit)
{//去除标点符号或数字
if(!isalpha(*cit)){
word.erase(cit);
--cit;//迭代器位置发生改变
}elseif(isupper(*cit)){//将大写字母改为小写
*cit=tolower(*cit);
}
}
}
voidDictProducer::processChineseWord(string&word)
{
autocit=word.begin();
for(;cit!=word.end();++cit)
{//去除数字
if(!isalnum(*cit)){
word.erase(cit);
--cit;
}
}
}
voidDictProducer::build_dict()//建立英文词典
{
for(auto&filePath:_englishFiles)
{
ifstreamifs(filePath);
if(!ifs){
cout<<"EnglishFileopenerror!"<<endl;
}
stringword;
while(ifs>>word)
{
processEnglishWord(word);
autocit=_dict.find(word);
if(word.size()>0&&cit==_dict.end()){
_dict.insert(std::make_pair(word,1));
}elseif(cit!=_dict.end()){
++cit->second;
}
}
}
}
voidDictProducer::build_cn_dict()
{
vector<string>words;
for(autofilePath:_chineseFiles)
{
ifstreamifs(filePath);
if(!ifs){
cout<<"Chinesefileopenerror!"<<endl;
}
stringsentence;
while(std::getline(ifs,sentence))
{
_splitTool->Cut(sentence);
}
}
vector<string>&results=_splitTool->getResult();
for(auto&res:results)
{
processChineseWord(res);
autocit=_dict.find(res);
if(cit==_dict.end()){
_dict.insert(std::make_pair(res,1));
}else{
++cit->second;
}
}
}
voidDictProducer::store_dict()
{
construct_indict();
ofstreamofs(_goleFilePath);
if(!ofs)
cout<<"Store_dictopenfileerror!"<<endl;
for(auto&mypair:_indict)
{
ofs<<mypair.first<<""<<mypair.second<<endl;
}
ofs.close();
}
voidDictProducer::construct_indict()
{
for(autodictpair:_dict){
_indict.push_back(dictpair);
}
}
==GetIndex:==
///=======================================
///File:GetIndex.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-1208:52:04
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__GETINDEX_H__
#define__GETINDEX_H__
#include<string>
#include<unordered_map>
#include<set>
#include<vector>
#include<utility>
#include<unordered_set>
usingnamespacestd;
classGetIndex
{
public:
GetIndex(conststring&,conststring&,conststring&);
~GetIndex(){}
voidconstruct_index();
voidstore_index();
private:
boolisEnglish(conststring&rhs)const;
vector<string>getOneCharacter(conststring&word);
string_sourceFilePath;
string_goleFilePath;
string_stopWordsFilePath;
vector<pair<string,int>>_dict;
unordered_set<string>_stopWords;
unordered_map<string,set<int>>_index;
};
#endif
///=======================================
///File:GetIndex.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-1209:00:11
///Dream:Don'tforgetyourdreams!
///======================================
#include"GetIndex.h"
#include<fstream>
#include<sstream>
#include<iostream>
usingnamespacestd;
GetIndex::GetIndex(conststring&sourceFilePath,conststring&goleFilePath,conststring&stopWordsFilePath)
:_sourceFilePath(std::move(sourceFilePath))
,_goleFilePath(std::move(goleFilePath))
,_stopWordsFilePath(std::move(stopWordsFilePath))
{
ifstreamifs(_sourceFilePath);
if(!ifs){
cout<<"GetIndexfileopenerror!"<<endl;
}
stringline;
while(getline(ifs,line))
{
istringstreamiss(line);
stringkey;
intvalue;
iss>>key>>value;
_dict.push_back(std::make_pair(key,value));
}
ifstreamifs1(_stopWordsFilePath);
if(!ifs1){
cout<<"fileopenerror!"<<endl;
}
stringstopWord;
while(ifs1>>stopWord,!ifs1.eof())
{
_stopWords.insert(stopWord);
}
}
vector<string>GetIndex::getOneCharacter(conststring&word)
{
vector<string>tmp;
autocit=word.begin();
while(cit<word.end())
{
if(224==(*cit&224))
{
stringoneCharacter;
oneCharacter.append(cit,cit+3);
tmp.push_back(oneCharacter);
cit+=3;
}elseif(240==(*cit&240)){
stringoneCharacter;
oneCharacter.append(cit,cit+4);
tmp.push_back(oneCharacter);
cit+=4;
}else
break;
}
returntmp;
}
boolGetIndex::isEnglish(conststring&rhs)const
{
charch=*(rhs.begin());
if(ch<0)
returnfalse;
returntrue;
}
#if0
boolGetIndex::isEnglish(conststring&rhs)const
{
charch=*(rhs.begin());
if(ch<0){
returnfalse;
}
returntrue;
}
#endif
voidGetIndex::construct_index()
{
for(size_ti=0;i!=_dict.size();++i)
{
stringtmp=_dict[i].first;
if(isEnglish(tmp))
{
for(autoch:tmp)
{
stringcharactor(1,ch);
if(isalpha(ch))
{
autocit=_index.find(charactor);
if(cit==_index.end())
{
set<int>smp;
smp.insert(i);
_index.insert(std::make_pair(charactor,smp));
}else{//已经存在了该字母的索引
cit->second.insert(i);
}
}
}
}else{//中文处理部分
vector<string>oneCharacterRally=getOneCharacter(tmp);
for(autooneCharacter:oneCharacterRally)
{//stop_words中不存在该单词,则加入索引中
if(_stopWords.find(oneCharacter)==_stopWords.end()){
autoit=_index.find(oneCharacter);
if(it==_index.end()){
set<int>tmp;
tmp.insert(i);
_index.insert(std::make_pair(oneCharacter,tmp));
}else{
it->second.insert(i);
}
}
}
}
}
}
voidGetIndex::store_index()
{
//ofs存储索引的内容
std::ofstreamofs(_goleFilePath);
if(!ofs){
cout<<"fileopenerror!"<<endl;
return;
}
for(autodata:_index)
{
ofs<<data.first<<"";
for(autolinenum:data.second)
{
ofs<<linenum<<"";
}
ofs<<endl;
}
ofs.close();
}
==SplitTool:==
///=======================================
///File:SplitTool.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-1217:12:01
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__SPLITTOOL_H__
#define__SPLITTOOL_H__
#include"../cppjieba/include/cppjieba/Jieba.hpp"//需要自己将cppjieba安装在项目目录下
#include"Configuration.h"
#include<string>
#include<vector>
usingnamespacestd;
usingnamespacecppjieba;
classSplitToolJieba
{
public:
SplitToolJieba(conststring&dict_path,conststring&model_path,conststring&user_dict_path,conststring&idfPath,conststring&stopWordPath)
:_jieba(dict_path,model_path,user_dict_path,idfPath,stopWordPath)
{}
~SplitToolJieba(){}
voidCut(conststring&sentence)
{
vector<string>tmp;
_jieba.Cut(sentence,tmp);
_result.insert(_result.end(),tmp.begin(),tmp.end());
}
vector<string>&getResult(){return_result;}
private:
vector<string>_result;
cppjieba::Jieba_jieba;
};
#endif
==main:==
///=======================================
///File:main.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-1220:38:50
///Dream:Don'tforgetyourdreams!
///======================================
#include"Configuration.h"
#include"SplitTool.h"
usingnamespacestd;
#include"DictProducer.h"
#include"GetIndex.h"
#include<iostream>
#include<memory>
constchar*constDICT_PATH="../cppjieba/dict/jieba.dict.utf8";
constchar*constHMM_PATH="../cppjieba/dict/hmm_model.utf8";
constchar*constUSER_DICT_PATH="../cppjieba/dict/user.dict.utf8";
constchar*constIDF_PATH="../cppjieba/dict/idf.utf8";
constchar*constSTOP_WORD_PATH="../cppjieba/dict/stop_words.utf8";
conststringGOLE_DICT_PATH="../server/data/dict.txt";
conststringGOLE_INDEX_PATH="../server/data/index.txt";
classSplitTool;
intmain(void)
{
Configuration*pconfig=Singleton<Configuration>::getInstance("configure.txt");
SplitToolJieba*ptool=newSplitToolJieba(DICT_PATH,HMM_PATH,USER_DICT_PATH,IDF_PATH,STOP_WORD_PATH);
DictProducermydictProducer(pconfig->getEnglishDir(),pconfig->getChineseDir(),GOLE_DICT_PATH,ptool);
mydictProducer.build_dict();//建立英语词典
mydictProducer.build_cn_dict();//建立中文词典
mydictProducer.store_dict();//储存词典
GetIndexmyindex(GOLE_DICT_PATH,GOLE_INDEX_PATH,"stop_words_zh.txt");
myindex.construct_index();//建立索引
myindex.store_index();//存储索引
Singleton<Configuration>::destroy();
return0;
}
在线部分:
img
==ConFiguration:==
///=======================================
///File:ConFiguration.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0610:32:43
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__CONFIGURATION_H__
#define__CONFIGURATION_H__
#include"Noncopyable.h"
#include<string>
#include<map>
#defineCONFPATH"/home/wtp/spell/server/conf/configure.txt"
usingnamespacestd;
namespacewd
{
classConfiguration
:publicNoncopyable
{
public:
Configuration(conststring&filePath);
~Configuration()=default;
stringgetDictDir()const;
stringgetIndexDir()const;
stringgetIp()const;
stringgetCache()const;
unsignedshortgetPort()const;
private:
string_filePath;
map<string,string>_conf;
};
};
template<typenameT>
classSingleton
{
public:
template<typename...Args>
staticT*getInstance(Args...args)
{
if(!_pInstance)
_pInstance=newT(args...);
return_pInstance;
}
staticvoiddestroy()
{
if(_pInstance)
delete_pInstance;
}
private:
Singleton();
~Singleton();
staticT*_pInstance;
};
template<typenameT>
T*Singleton<T>::_pInstance=NULL;
#endif
///=======================================
///File:ConFiguration.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0715:24:14
///Dream:Don'tforgetyourdreams!
///======================================
#include"ConFiguration.h"
#include<stdlib.h>
#include<utility>
#include<fstream>
#include<iostream>
usingnamespacestd;
usingnamespacewd;
wd::Configuration::Configuration(conststring&filePath)
:_filePath(std::move(filePath))
{
ifstreamifs(_filePath);
if(!ifs){
cout<<"fileopenerror!"<<endl;
}
stringkey,value;
while(ifs>>key)
{
ifs>>value;
_conf.insert(std::make_pair(key,value));
}
ifs.close();
}
stringwd::Configuration::getDictDir()const
{
autocit=_conf.find("mydict");
if(cit==_conf.end())
return"";
else
returncit->second;
}
stringwd::Configuration::getIndexDir()const
{
autocit=_conf.find("myindex");
if(cit==_conf.end())
return"";
else
returncit->second;
}
stringwd::Configuration::getIp()const
{
autocit=_conf.find("myip");
if(cit==_conf.end())
return"";
else
returncit->second;
}
unsignedshortwd::Configuration::getPort()const
{
autocit=_conf.find("myport");
if(cit==_conf.end())
return0;
else
returnatoi(cit->second.c_str());
}
stringwd::Configuration::getCache()const
{
autocit=_conf.find("mycache");
if(cit==_conf.end())
return"";
else
returncit->second;
}
==Acceptor:==
///=======================================
///File:Acceptor.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0523:47:05
///Dream:Don'tforgetyourdreams!
///======================================
#ifndef__WD_ACCEPTOR_H__
#define__WD_ACCEPTOR_H__
#include"Socket.h"
#include"InetAddress.h"
namespacewd
{
classAcceptor
{
public:
Acceptor(intlistenfd,constInetAddress&addr);
voidready();//服务器监听准备
intaccept();//服务器接收新连接
intfd()const{return_listenSock.fd();}
private:
voidsetReuseAddr(boolon);//设置地址重用
voidsetReusePort(boolon);//设置端口重用
voidbind();//绑定
voidlisten();//监听
Socket_listenSock;
InetAddress_addr;
};
}
#endif
///=======================================
///File:Acceptor.cc
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0523:52:12
///Dream:Don'tforgetyourdreams!
///======================================
#include<iostream>
#include"Acceptor.h"
#include"SocketUtil.h"
namespacewd
{
Acceptor::Acceptor(intlistenfd,constInetAddress&addr)
:_listenSock(listenfd)
,_addr(addr)
{}
voidAcceptor::ready()
{
setReuseAddr(true);
setReusePort(true);
bind();
listen();
}
intAcceptor::accept()
{
intpeerfd=::accept(_listenSock.fd(),NULL,NULL);
if(-1==peerfd)
{
perror("accepterror!");
}
returnpeerfd;
}
voidAcceptor::setReuseAddr(boolflag)
{
inton=(flag?1:0);
if(::setsockopt(_listenSock.fd()
,SOL_SOCKET
,SO_REUSEADDR
,&on
,static_cast<socklen_t>(size_t(on)))==-1)
{
perror("setsockoptreuseaddrerror!");
::close(_listenSock.fd());
exit(EXIT_FAILURE);
}
}
voidAcceptor::setReusePort(boolflag)
{
#ifndefSO_REUSEPORT
inton=(flag?1:0);
if(::setsockopt(_listenSock.fd()
,SOL_SOCKET
,SO_REUSEADDR
,&on
,static_cast<socklen_t>(size_t(on)))==-1)
{
perror("setsockoptreuseporterror!");
::close(_listenSock.fd());
exit(EXIT_FAILURE);
}
#else
if(flag)
{
fprintf(stderr,"SO_REUSEPORTisnotsupported!\n");
}
#endif
}
voidAcceptor::bind()
{
if(-1==::bind(_listenSock.fd()
,(conststructsockaddr*)_addr.getSockAddrPtr()
,sizeof(InetAddress)))
{
perror("binderror!");
::close(_listenSock.fd());
exit(EXIT_FAILURE);
}
}
voidAcceptor::listen()
{
if(-1==::listen(_listenSock.fd(),10))
{
perror("listenerror!");
::close(_listenSock.fd());
exit(EXIT_FAILURE);
}
}
}
#if0
intmain()
{
std::cout<<"Acceptoriscorrect!"<<std::endl;
}
#endif
==Condition.h:==
#ifndef__WD_CONDITION_H__
#define__WD_CONDITION_H__
#include"Noncopyable.h"
#include"MutexLock.h"
#include<pthread.h>
namespacewd
{
classCondition
:Noncopyable
{
public:
Condition(MutexLock&mutex)
:_mutex(mutex)
{pthread_cond_init(&_cond,NULL);}
~Condition()
{pthread_cond_destroy(&_cond);}
voidwait()
{pthread_cond_wait(&_cond,_mutex.getMutexLockPtr());}
voidnotify()
{pthread_cond_signal(&_cond);}
voidnotifyAll()
{pthread_cond_broadcast(&_cond);}
private:
pthread_cond_t_cond;
MutexLock&_mutex;
};
}
#endif
==Cache:==
///=======================================
///File:Cache.h
///Author:wtptorres(1584292712@qq.com)
///Date:2019-06-0519:52:40
///Dream:Don'tforgetyourdreams!
///======================================
如需转载,请注明文章出处和来源网址:http://www.divcss5.com/html/h56751.shtml