欢迎来到DIVCSS5查找CSS资料与学习DIV CSS布局技术!
  目录
 
  我的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