小型搜索引擎项目

我的SearchEngine开发文档


相关配置文件及准备工作:

我的主要文件夹分为三个:分别为客户端,cppjieba分词库,服务器部分

客户端部分:内部为客户端源码及运行程序

cppjieba分词库部分,就不赘述,请自行安装
服务器部分:最为重要的配置文件及数据部分,头文件在include,实现文件在src里面


演示效果(中文):

==启动时服务器:==

==客户端连入时时服务器:==

==输入“百度”==

==输入“周杰伦”==

==输入“清华大学”==

==输入“微信”==


演示效果(英语):

==启动时服务器:==

==客户端连入时时服务器:==

==输入“baidu":==

==输入"github":==

==输入"word":==


代码部分:

客户端代码:

==Client:==
 ///=======================================
 /// File:    Client.cc
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-22 21:54:36
 /// Dream:   Don't forget your dreams!
 /// ======================================
#include "json/json.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <string>
#include <iostream>
using std::cout;
using std::endl;
using std::string;
#define ERR_EXIT(m) \
    do { \
        perror(m);\
        exit(EXIT_FAILURE);\
    }while(0)

void do_service(int sockfd);
size_t readn(int sockfd,char *buf,size_t count)
{
    size_t nleft = count;
    char * pbuf = buf;
    while(nleft > 0)
    {
        int nread = read(sockfd,pbuf,nleft);
        if( nread == -1)
        {
            if(errno == EINTR)
                continue;
            return EXIT_FAILURE;
        }else if(nread == 0 )
            break;
        pbuf += nread;
        nleft -= nread;
    }
    return (count - nleft);
}
size_t writen(int sockfd,const char *buf,size_t count)
{
    size_t nleft = count;
    const char * pbuf = buf;
    while(nleft > 0)
    {
        int nwrite = write(sockfd,pbuf,nleft);
        if(nwrite == -1)
        {
            if(errno == EINTR)
                continue;
            return EXIT_FAILURE;
        }
        nleft -= nwrite;
        pbuf += nwrite;
    }
    return (count -nleft);
}
int main(int argc, const char *argv[])
{
    if(argc !=3)
    {
        printf("./client IP Port");
        return -1;
    }
    int peerfd = socket(PF_INET, SOCK_STREAM, 0);
    if(peerfd == -1)
        ERR_EXIT("socket");

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof addr);
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(argv[1]);
    addr.sin_port = htons(atoi(argv[2]));
    socklen_t len = sizeof addr;
    if(connect(peerfd, (struct sockaddr*)&addr, len) == -1)
        ERR_EXIT("Connect");

    char buf[1024];
    int length;
    memset(buf, 0, sizeof(buf));
    readn(peerfd,(char*)&length,sizeof(int));
    readn(peerfd, buf, length);
    cout<<buf<<endl;
    do_service(peerfd);


    return 0;
}
void jsonPara(const string strData)
{
    Json::Reader reader;
    Json::Value DevsJson;
    reader.parse(strData,DevsJson);
    int siNum = DevsJson.size();
    for(int i = 0;i< siNum;++i)
    {
        Json::Value Dev = DevsJson[i];
        string Devstr = Dev.toStyledString();
        cout << Devstr;
    }
}


void do_service(int sockfd)
{
    char recvbuf[1024] = {0};
    char sendbuf[1024] = {0};
    while(1)
    {
        bzero(sendbuf,sizeof(sendbuf));
        read(0,sendbuf,sizeof(sendbuf)-1);
        write(sockfd,sendbuf,strlen(sendbuf));
        int len;
        bzero(recvbuf,sizeof(recvbuf));
        readn(sockfd,(char*)&len,sizeof(int));
        readn(sockfd,recvbuf,len);
        jsonPara(string(recvbuf));
    }
}
#if 0
void JsonPara(const string strData)
{
    Json::Reader reader;
    Json::Value DevsJson;
    reader.parse(strData,DevsJson);
    int siNum =DevsJson.size();
    for(int i =0;i<siNum;++i)
    {
        Json::Value Dev =DevsJson[i];
        string Devstr =Dev.toStyledString();
        if(Devstr.c_str())
            cout<<Devstr;
    }
}
#endif



服务器代码:

==Acceptor:==
 ///=======================================
 /// File:    Acceptor.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-22 23:47:05
 /// Dream:   Don't forget your dreams!
 /// ======================================
 
#ifndef  __WD_ACCEPTOR_H__
#define  __WD_ACCEPTOR_H__

#include "Socket.h"
#include "InetAddress.h"

namespace wd
{
class Acceptor
{
public:
    Acceptor(int listenfd,const InetAddress & addr);
    void ready();
    int accept();
    int fd()const {return _listenSock.fd();}
private:
    void setReuseAddr(bool on);
    void setReusePort(bool on);
    void bind();
    void listen();
    Socket _listenSock;
    InetAddress _addr;
};
}

#endif
 ///=======================================
 /// File:    Acceptor.cc
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-05 23:52:12
 /// Dream:   Don't forget your dreams!
 /// ======================================
#include <iostream>
#include "Acceptor.h"
#include "SocketUtil.h"

namespace wd
{
Acceptor::Acceptor(int listenfd,const InetAddress & addr)
:_listenSock(listenfd)
,_addr(addr)
{}

void Acceptor::ready()
{
    setReuseAddr(true);
    setReusePort(true);
    bind();
    listen();
}
int Acceptor::accept()
{
    int peerfd=::accept(_listenSock.fd(),NULL,NULL);
    if(-1==peerfd)
    {
        perror("accept error!");
    }
    return peerfd;
}
void Acceptor::setReuseAddr(bool flag)
{
    int on=(flag?1:0);
    if(::setsockopt(_listenSock.fd()
                    ,SOL_SOCKET
                    ,SO_REUSEADDR
                    ,&on
                    ,static_cast<socklen_t>(size_t(on)))==-1)
    {
        perror("setsockopt reuseaddr error!");
        ::close(_listenSock.fd());
        exit(EXIT_FAILURE);
    }
}

void Acceptor::setReusePort(bool flag)
{
#ifdef SO_REUSEPORT
    int on =(flag?1:0);
    if(::setsockopt(_listenSock.fd()
                    ,SOL_SOCKET
                    ,SO_REUSEPORT
                    ,&on
                    ,static_cast<socklen_t>(sizeof(on)))==-1)
    {
        perror("setsockopt reuseport error!");
        ::close(_listenSock.fd());
        exit(EXIT_FAILURE);
    }
#else
    if(flag)
    {
        fprintf(stderr,"SO_REUSEPORT is not supported!\n");
    }
#endif
}

void Acceptor::bind()
{
    if(-1==::bind(_listenSock.fd()
                  ,(const struct sockaddr*)_addr.getSockAddrPtr()
                  ,sizeof(InetAddress)))
    {
        perror("bind error!");
        ::close(_listenSock.fd());
        exit(EXIT_FAILURE);
    }
}
void Acceptor::listen()
{
    if(-1==::listen(_listenSock.fd(),10))
    {
        perror("listen error!");
        ::close(_listenSock.fd());
        exit(EXIT_FAILURE);
    }
}

}
==Cache:==
 ///=======================================
 /// File:    Cache.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-25 19:52:40
 /// Dream:   Don't forget your dreams!
 /// ======================================
 
#ifndef __CACHE_H__
#define __CACHE_H__
#include <unordered_map>
#include <string>
using namespace std;
namespace wd
{
    class Cache
    {
    public:
        void addElement(string,string);
        void readFromFile(string);
        void writeToFile(string);
        void update(const Cache&);
        bool find(string querry);
        string &operator[](string key);
    private:
        unordered_map<string,string>_hashTable;
    };
};
#endif
 ///=======================================
 /// File:    Cache.cc
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-05 20:01:25
 /// Dream:   Don't forget your dreams!
 /// ======================================
#include "Cache.h"
#include <fstream>
#include <utility>
#include <iostream>
using namespace std;
using namespace wd;

void Cache::addElement(string querry,string result)
{
    _hashTable[querry]=result;
}

void Cache::readFromFile(string filePath)
{
    ifstream ifs(filePath);
    if(!ifs){
        cout<<" file open error!"<<endl;
        return;
    }
    string querry,result;
    while(ifs>>querry,!ifs.eof())
    {
        ifs>>result;
        _hashTable[querry]=result;
    }
}
#if 0
void Cache::writeToFile(string filePath)
{
    ofstream ofs(filePath);
    if(!ofs){
        cout<<""<<endl;
        return;
    }
    for(auto &mypair:_hashTable)
    {
        ofs<<mypair.first<<" ";
        ofs<<mypair.second<<endl;
    }
}

void Cache::update(const Cache & cache)
{   
    for(auto &mypair:cache._hashTable)
    {
        auto cit =_hashTable.find(mypair.first);
        if(cit==_hashTable.end())
        {
            _hashTable.insert(std::move(mypair));
        }
    }
}
#endif

void Cache::writeToFile(string filePath)
{
    ofstream ofs(filePath);
    if(!ofs){
        cout<<"file write error!"<<endl;
        return;
    }
    for(auto &mypair:_hashTable)
    {
        ofs<<mypair.first<<" ";
        ofs<<mypair.second<<endl;
    }
}

void Cache::update(const Cache & cache)
{
    for(auto &mypair:cache._hashTable)
    {
        auto cit =_hashTable.find(mypair.first);
        if(cit==_hashTable.end())
        {
            _hashTable.insert(std::move(mypair));
        }
    }
}

bool Cache::find(string querry)
{
    auto cit =_hashTable.find(querry);
    if(cit==_hashTable.end())
        return false;
    return true;
}

string &Cache::operator[](string key)
{
    return _hashTable[key];
}

#if 0
int main()
{
    cout<<"cache is correct!"<<endl;
}
#endif
==CacheManger:==
 ///=======================================
 /// File:    CacheManger.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-25 20:51:09
 /// Dream:   Don't forget your dreams!
 /// ======================================
 
#ifndef __CACHEMANGER_H__
#define __CACHEMANGER_H__
#include "Cache.h"
#include <vector>
#define THREADNUM 4

using std::vector;
namespace wd
{
    class CacheManger
    {
    public:
        CacheManger(string filePath);
        void init(string);
        Cache & getCache(size_t);
        void periodicUpdate();
    private:
        string _cacheFilePath;
        vector<Cache>_cacheList;
    };
};

#endif
 ///=======================================
 /// File:    CacheManger.cc
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-05 20:56:50
 /// Dream:   Don't forget your dreams!
 /// ======================================
#include "CacheManger.h"
#include <iostream>
#include <fstream>
#include <utility>
#include <iostream>
using namespace std;
using namespace wd;

CacheManger::CacheManger(string cacheFilePath)
{
    init(cacheFilePath);
}
             
void CacheManger::init(string cacheFilePath)
{
    _cacheFilePath=cacheFilePath;
    _cacheList.reserve(THREADNUM);
    Cache tmp;
    tmp.readFromFile(_cacheFilePath);
    for(size_t i=0;i!=THREADNUM;++i)
    {
        _cacheList.push_back(std::move(tmp));
    }
}

Cache & CacheManger::getCache(size_t number)
{
    return _cacheList[number];
}

void CacheManger::periodicUpdate()
{
    auto cit=_cacheList.begin();
    Cache lastWrite=*(cit ++);
    for(;cit<_cacheList.end();++cit)
    {
        lastWrite.update(*cit);
    }
    for(cit=_cacheList.begin()+1;cit!=_cacheList.end();++cit)
    {
        (*cit).update(lastWrite);
    }
    lastWrite.writeToFile(_cacheFilePath);
}
==Condition:==
 ///=======================================
 /// File:    Condition.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-26 10:32:43
 /// Dream:   Don't forget your dreams!
 /// ======================================
#ifndef __WD_CONDITION_H__
#define __WD_CONDITION_H__

#include "Noncopyable.h"
#include "MutexLock.h"
#include <pthread.h>

namespace wd
{
    class Condition
    :Noncopyable
    {
    public:
        Condition(MutexLock &mutex)
        :_mutex(mutex)
        {pthread_cond_init(&_cond,NULL);}
    
        ~Condition()
        {pthread_cond_destroy(&_cond);}
    
        void wait()
        {pthread_cond_wait(&_cond,_mutex.getMutexLockPtr());}
    
        void notify()
        {pthread_cond_signal(&_cond);}
    
        void notifyAll()
        {pthread_cond_broadcast(&_cond);}
    private:
        pthread_cond_t _cond;
        MutexLock & _mutex;
    };

}
#endif
==ConFiguration:==
 ///=======================================
 /// File:    ConFiguration.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-26 10:32:43
 /// Dream:   Don't forget your dreams!
 /// ======================================

#ifndef __CONFIGURATION_H__
#define __CONFIGURATION_H__
#include "Noncopyable.h"
#include <string>
#include <map>
#include <set>
using std::string;
using std::map;
using std::set;

class Configuration
{
public:
    Configuration(const string &filePath);
    map<string,string>& getConfigMap();
    set<string>& getStopWordList();
    Configuration &operator=(const Configuration & rhs);
    string getIp()const;
    unsigned short getPort() const;
private:
    string _filePath;
    map<string,string> _configMap;
    set<string> _stopWordList;
};

template<typename T>
class Singleton
{
public:
    template<typename ...Args>
    static T *getInstance(Args ...args)
    {
        if(!_pInstance)
            _pInstance=new T(args ...);
        return _pInstance;
    }

    static void destroy()
    {
        if(_pInstance)
            delete _pInstance;
    }
private:
    Singleton();
    ~Singleton();
    static T *_pInstance;
};

template<typename T>
T *Singleton<T>::_pInstance =NULL;
#endif
 ///=======================================
 /// File:    ConFiguration.cc
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-07 15:24:14
 /// Dream:   Don't forget your dreams!
 /// ======================================

#include "ConFiguration.h"
#include <stdlib.h>
#include <utility>
#include <fstream>
#include <iostream>
using namespace std;
using namespace wd;

Configuration::Configuration(const string & filePath)
:_filePath(std::move(filePath))
{
    ifstream ifs(_filePath);
    if(!ifs){
        cout<<"file open error!"<<endl;
    }
    string key,value;
    while(ifs>>key,!ifs.eof())
    {
        ifs>>value;
        _configMap.insert(std::make_pair(key,value));
    }
    ifs.close();
}

map<string,string>& Configuration::getConfigMap()
{
    return _configMap;
}

set<string> & Configuration::getStopWordList()
{
    string stopWordPath=_configMap["myStopWord"];
    ifstream ifs(stopWordPath);
    if(!ifs){
        cout<<"getStopWordList file open error!"<<endl;
        return _stopWordList;
    }
    string stopword;
    while(ifs>>stopword)
    {
        _stopWordList.insert(stopword);
    }
    return _stopWordList;
}

Configuration & Configuration::operator=(const Configuration & rhs)
{
    _filePath=rhs._filePath;
    _configMap=rhs._configMap;
    _stopWordList=rhs._stopWordList;
    return *this;
}
string Configuration::getIp()const
{
    auto cit =_configMap.find("myip");
    if(cit ==_configMap.end()){
        return "";
    }
    return cit->second;
}

unsigned short Configuration::getPort() const
{
    auto cit =_configMap.find("myport");
    if(cit==_configMap.end())
        return 0;
    else
        return atoi(cit->second.c_str());
}

==EpollPoller:==
 ///=======================================
 /// File:    EpollPoller.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-25 11:03:36
 /// Dream:   Don't forget your dreams!
 /// ======================================

#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>

namespace wd
{
class Acceptor;
class EpollPoller
:Noncopyable
{
public:
    typedef TcpConnection::TcpConnectionCallback EpollCallback;
    typedef  std::function<void()> Functor;
    EpollPoller(Acceptor &acceptor);
    ~EpollPoller();

    void loop();
    void unloop();
    void runInLoop(const Functor && cb);
    void doPendingFunctors();
    void wakeup();

    void setConnectionCallback(EpollCallback cb);
    void setMessageCallback(EpollCallback cb);
    void setCloseCallback(EpollCallback cb);
private:
    void waitEpollfd();
    void handleConnection();
    void handleMessage(int peerfd);
    void handleRead();

    Acceptor & _acceptor;
    int _epollfd;
    int _eventfd;
    int _listenfd;
    bool _isLooping;

    MutexLock _mutex;
    std::vector<Functor> _pendingFunctors;

    typedef std::vector<struct epoll_event>Eventlist;
    Eventlist _eventList;

    typedef std::map<int,TcpConnectionPtr> ConnectionMap;
    ConnectionMap _connMap;
    EpollCallback _onConnectionCb;
    EpollCallback _onMessageCb;
    EpollCallback _onCloseCb;
};
}
#endif
 ///=======================================
 /// File:    EpollPoller.cc
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-07 15:42:54
 /// Dream:   Don't forget your dreams!
 /// ======================================

#include "EpollPoller.h"
#include "SocketUtil.h"
#include "Acceptor.h"
#include <assert.h>
#include <iostream>
using namespace std;

namespace wd
{
    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);
    }
    
    void EpollPoller::loop()
    {
        _isLooping=true;
        while(_isLooping)
        {
            waitEpollfd();
        }
    }

    void EpollPoller::unloop()
    {
        if(_isLooping)
            _isLooping=false;
    }

    void EpollPoller::setConnectionCallback(EpollCallback cb)
    {
        _onConnectionCb=cb;
    }
    
    void EpollPoller::setMessageCallback(EpollCallback cb)
    {
        _onMessageCb=cb;
    }
    
    void EpollPoller::setCloseCallback(EpollCallback cb)
    {
        _onCloseCb=cb;
    }
    void EpollPoller::waitEpollfd()
    {
        int nready;
        do
        {
            nready =::epoll_wait(_epollfd,&(*_eventList.begin()),_eventList.size(),10000);
                
        }while(-1==nready && errno ==EINTR);

        if(-1==nready){
            perror("epoll wait error!");
            exit(EXIT_FAILURE);
        }else if(0==nready){
            cout<<"epoll_wait timeout!"<<endl;
        }else{
            if(nready==static_cast<int>(_eventList.size())){
                _eventList.resize(_eventList.size()*2);
            }

            for(int idx=0;idx!=nready;++idx)//正宗罗老师循环体(TwT)
            {
                if(_eventList[idx].data.fd ==_listenfd)
                {
                    if(_eventList[idx].events & EPOLLIN)
                    {
                        handleConnection();
                    }
                }else if(_eventList[idx].data.fd ==_eventfd){
                    handleRead();
                    cout<<">>doPendingFunctors()"<<endl;
                    doPendingFunctors();
                }else{
                    if(_eventList[idx].events & EPOLLIN){
                        handleMessage(_eventList[idx].data.fd);
                    }
                }
            }
        }
    }

    void EpollPoller::handleConnection()
    {
        int peerfd=_acceptor.accept();
        addEpollFdRead(_epollfd,peerfd);
        TcpConnectionPtr conn(new TcpConnection(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();
    }

    void EpollPoller::handleMessage(int peerfd)
    {
        bool isClosed=isConnectionClosed(peerfd);
        ConnectionMap::iterator it =_connMap.find(peerfd);
        assert(it!=_connMap.end());

        if(isClosed)
        {
            it->second->handleCloseCallback();
            delEpollReadFd(_epollfd,peerfd);
            _connMap.erase(it);
        }else{
            it->second->handleMessageCallback();
        }
    }

    void EpollPoller::runInLoop(const Functor && cb)
    {
        {
            MutexLockGuard mlg(_mutex);
            _pendingFunctors.push_back(std::move(cb));
        }
        wakeup();
    }

    void EpollPoller::doPendingFunctors()
    {
        std::vector<Functor>tmp;
        {
            MutexLockGuard mlg(_mutex);
            tmp.swap(_pendingFunctors);
        }
        for(auto & functor:tmp)
        {
            functor();
        }
    }

    void EpollPoller::handleRead()
    {
        uint64_t howmany;
        int ret=::read(_eventfd,&howmany,sizeof(howmany));
        if(ret !=sizeof(howmany))
        {
            perror("read error!");
        }
    }

    void EpollPoller::wakeup()
    {
        uint64_t one =1;
        int ret =::write(_eventfd,&one,sizeof(one));
        if(ret!=sizeof(one))
        {
            perror("write error!");
        }
    }
}
 
==InetAddress:==
 ///=======================================
 /// File:    InetAddress.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-22 21:55:19
 /// Dream:   Don't forget your dreams!
 /// ======================================
#ifndef __WD_INETADDRESS_H__
#define __WD_INETADDRESS_H__
#include <netinet/in.h>
#include <string>
namespace wd
{
class InetAddress
{
    public:
        InetAddress(short port);
        InetAddress(const char *pIp,short port);
        InetAddress(const struct sockaddr_in & addr);
        std::string ip()const;
        unsigned short port() const;
        const struct sockaddr_in *getSockAddrPtr() const;
    private:
        struct sockaddr_in _addr;
    };
}
#endif
 ///=======================================
 /// File:    InetAddress.cc
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-07 20:55:18
 /// Dream:   Don't forget your dreams!
 /// ======================================

#include "InetAddress.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>

namespace wd
{
InetAddress::InetAddress(short port)
{
    ::memset(&_addr,0,sizeof(_addr));
    _addr.sin_family=AF_INET;
    _addr.sin_port=htons(port);
    _addr.sin_addr.s_addr=INADDR_ANY;
}

InetAddress::InetAddress(const char * pIp,short port)
{
    ::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(const struct sockaddr_in & addr)
:_addr(addr)
{}

const struct sockaddr_in * InetAddress::getSockAddrPtr()const
{
    return & _addr;
}

std::string InetAddress::ip()const
{
    return std::string(inet_ntoa(_addr.sin_addr));
}

unsigned short InetAddress::port() const
{
    return ntohs(_addr.sin_port);
}

}
==MutexLock:==
 ///=======================================
 /// File:    MutexLock.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-24 10:32:43
 /// Dream:   Don't forget your dreams!
 /// ======================================
#ifndef  __WD_MUTEXLOCK_H__
#define  __WD_MUTEXLOCK_H__

#include "Noncopyable.h"
#include <pthread.h>

namespace wd
{
    class MutexLock
    :Noncopyable
    {
    public:
        MutexLock()
        {pthread_mutex_init(&_mutex,NULL);}
        ~MutexLock()
        {pthread_mutex_destroy(&_mutex);}
        void lock()
        {pthread_mutex_lock(&_mutex);}
        void unlock()
        {pthread_mutex_unlock(&_mutex);}
        pthread_mutex_t *getMutexLockPtr()
        {return &_mutex;}
    private:
        pthread_mutex_t _mutex;
};

class MutexLockGuard
{
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-06 11:12:19
 /// Dream:   Don't forget your dreams!
 /// ======================================

#ifndef __MYDICT_H__
#define __MYDICT_H__
#include <string>
#include <vector>
#include <map>
#include <utility>
#include <set>
#include <fstream>
#include <iostream>
#include <sstream>
using namespace std;
namespace wd
{
    struct MyResult
    {
        string _word;
        int _iFreq;//词频
        int _iDist;//最小编辑距离
    };
    
    class Mydict
    {
    public:
        Mydict(const string dictDir,const string indexDir)
        {
            ifstream ifs1(dictDir),ifs2(indexDir);
            if(!ifs1||!ifs2)
                cout<<"Mydict open file error!"<<endl;
            string key;
            int value;
            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));
            }
            string line;
            while(std::getline(ifs2,line))
            {
                istringstream iss(line);
                string ikey;
                int ivalue;
                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
==Noncopyable:==
 ///=======================================
 /// File:    Noncopyable.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-22 23:47:05
 /// Dream:   Don't forget your dreams!
 /// ======================================

#ifndef __WD_NONCOPYABLE_H__
#define __WD_NONCOPYABLE_H__

namespace  wd
{
    class Noncopyable
    {
    protected:
        Noncopyable(){}
        ~Noncopyable(){}
    private:
        Noncopyable(const Noncopyable &);
        Noncopyable & operator=(const Noncopyable &);
    
    };
}
#endif

==Socket:==
 ///=======================================
 /// File:    Socket.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-23 21:46:26
 /// Dream:   Don't forget your dreams!
 /// ======================================
 
#ifndef __WD_SOCKET_H__
#define __WD_SOCKET_H__
#include "Noncopyable.h"
namespace wd
{
    class InetAddress;
    class Socket
    :Noncopyable
    {
    public:
        Socket(int socket);
        Socket();
        ~Socket();
    
        void shutdownWrite();
        int fd()const {return _sockfd;}
        void nonblock();
        static InetAddress getLocalAddr(int socketfd);
        static InetAddress getPeerAddr(int sockfd);
    private:
        int _sockfd;
    };
}
#endif
 

 ///=======================================
 /// File:    Socket.cc
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-07 20:38:20
 /// Dream:   Don't forget your dreams!
 /// ======================================

#include "Socket.h"
#include "SocketUtil.h"
#include "InetAddress.h"

namespace wd
{
Socket::Socket(int sockfd)
:_sockfd(sockfd)
{}

Socket::Socket()
:_sockfd(createSocketFd())
{}

Socket::~Socket()
{
    ::close(_sockfd);
}

void Socket::nonblock()
{
    setNonblock(_sockfd);
}

void Socket::shutdownWrite()
{
    if(-1==::shutdown(_sockfd,SHUT_WR)){
        perror("shutdown write error!");
    }
}

InetAddress Socket::getLocalAddr(int sockfd)
{
    struct sockaddr_in addr;
    socklen_t len=sizeof(sockaddr_in);
    if(-1==::getsockname(sockfd,(struct sockaddr *)&addr,&len)){
        perror("getsockname error!");
    }
    return InetAddress(addr);
}

InetAddress Socket::getPeerAddr(int sockfd)
{
    struct sockaddr_in addr;
    socklen_t len=sizeof(sockaddr_in);
    if(-1==::getpeername(sockfd,(struct sockaddr *)&addr,&len)){
        perror("getpeername error!");
    }
    return InetAddress(addr);
    
}

}

==SocketIO:==
 ///=======================================
 /// File:    SocketIO.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-22 17:10:23
 /// Dream:   Don't forget your dreams!
 /// ======================================

#ifndef __SOCKETIO_H__
#define __SOCKETIO_H__
#include <stdio.h>

namespace wd
{
    class SocketIO
    {
    public:
        SocketIO(int sockfd);
        size_t readn(char *buf,size_t count);
        size_t writen(const char *buf,size_t count);
        size_t readline(char *buf,size_t max_len);
    private:
        size_t recv_peek(char *buf,size_t count);
        int _sockfd;
    };
}
#endif

 ///=======================================
 /// File:    SocketIO.cc
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-07 21:56:34
 /// Dream:   Don't forget your dreams!
 /// ======================================

#include "SocketIO.h"
#include "SocketUtil.h"
namespace wd
{
SocketIO::SocketIO(int sockfd)
:_sockfd(sockfd)
{}

size_t SocketIO::readn(char *buf,size_t count)
{
    size_t nleft =count;
    char *pbuf=buf;
    while(nleft>0)
    {
        int nread =::read(_sockfd,pbuf,nleft);
        if(-1==nread)
        {
            if(errno ==EINTR|| errno ==EAGAIN)//忽略中断信号
                continue;
            return EXIT_FAILURE;
        }else if(0==nread){
            break;
        }
        pbuf =pbuf+nread;
        nleft=nleft-nread;
    }
    return (count -nleft);
}

size_t SocketIO::writen(const char * buf,size_t count)
{
    size_t nleft =count;
    const char *pbuf=buf;
    while(nleft >0)
    {
        int nwrite=::write(_sockfd,pbuf,nleft);
        if(-1==nwrite)
        {
            if(errno ==EINTR)
                continue;
            return EXIT_FAILURE;
        }
        nleft =nleft -nwrite;
        pbuf =pbuf +nwrite;
    }
    return (count -nleft);
}
size_t SocketIO::recv_peek(char *buf,size_t count)
{
    int nread;
    do{
        nread=::recv(_sockfd,buf,count,MSG_PEEK);
    }while(-1==nread && errno ==EINTR);
    return nread;
}

size_t SocketIO::readline(char *buf,size_t maxlen)
{
    size_t nleft =maxlen-1;
    char *pbuf=buf;
    size_t total=0;
    while(nleft>0)
    {
        size_t nread =recv_peek(pbuf,nleft);
        if(nread<=0)
            return nread;
        for(size_t idx =0;idx!=nread;++idx){//检查换行符
            if(pbuf[idx]=='\n'){
                size_t nsize =idx +1;
                if(readn(pbuf,nsize)!=nsize)
                    return EXIT_FAILURE;
                pbuf +=nsize;
                total +=nsize;
                *pbuf=0;
                return total;
            }
        }
        if(readn(pbuf,nread)!=nread)
            return EXIT_FAILURE;
        pbuf +=nread;
        nleft -=nread;
        total +=nread;
    }
    *pbuf=0;
    return maxlen-1;
}

}

==SocketUtil:==
 ///=======================================
 /// File:    SocktUtil.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-05 22:01:30
 /// Dream:   Don't forget your dreams!
 /// ======================================

#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>
namespace wd
{
inline int createSocketFd()
{
    int fd=::socket(AF_INET,SOCK_STREAM,0);
    if(-1==fd)
    {
        perror("socket create error!");
    }
    return fd;
}

inline void setNonblock(int fd)
{
    int flags=::fcntl(fd,F_GETFL,0);
    flags |= O_NONBLOCK;
    ::fcntl(fd,F_SETFL,flags);
}

inline int createEpollFd()
{
    int efd=::epoll_create1(0);
    if(-1==efd)
    {
        perror("epoll create1 error!");
        exit(EXIT_FAILURE);
    }
    return efd;
}

inline int createEventFd()
{
    int evtfd=::eventfd(0,EFD_NONBLOCK|EFD_CLOEXEC);
    if(-1==evtfd)
    {
        perror("eventfd create error!");
    }
    return evtfd;
}
inline void addEpollFdRead(int efd,int fd)
{
    struct epoll_event ev;
    ev.data.fd=fd;
    ev.events=EPOLLIN;
    int ret=epoll_ctl(efd,EPOLL_CTL_ADD,fd,&ev);
    if(-1==ret)
    {
        perror("epoll ctl add error!");
        exit(EXIT_FAILURE);
    }
}
inline void delEpollReadFd(int efd,int fd)
{
    struct epoll_event ev;
    ev.data.fd=fd;
    int ret=epoll_ctl(efd,EPOLL_CTL_DEL,fd,&ev);
    if(-1==ret)
    {
        perror("epoll ctl delete error!");
        exit(EXIT_FAILURE);
    }
}

inline size_t recvPeek(int sockfd,void *buf,size_t len)//作用是预览数据
{
    int nread;
    do{
        nread=::recv(sockfd,buf,len,MSG_PEEK);
    }while(nread==-1 && errno ==EINTR);
    return nread;
}

inline bool isConnectionClosed(int sockfd)//通过预览数据,判断conn是否关闭
{
    char buf[1024];
    int nread=recvPeek(sockfd,buf,sizeof(buf));
    if(-1==nread)
    {
        perror("recvPeek error!");
        return true;
    }
    return (0==nread);
}
}
#endif

==TaskQueue:==
#ifndef __WD_TASKQUEUE_H__
#define __WD_TASKQUEUE_H__

#include "MutexLock.h"
#include "Condition.h"
#include <queue>
#include <functional>

namespace wd
{
typedef std::function<void()>Task;

class TaskQueue
{
public:
    TaskQueue(size_t queSize)
    :_queSize(queSize)
    ,_mutex()
    ,_notFull(_mutex)
    ,_notEmpty(_mutex)
    ,_flag(true)
    {}

    void push(Task &&task);
    Task pop();
    bool empty()const
    {
        return _que.size()==0;
    }
    bool full()const
    {return _que.size()==_queSize;}
    void wakeup()
    {
        _flag=false;
        _notEmpty.notifyAll();
    }
private:
    size_t _queSize;
    std::queue<Task> _que;
    MutexLock _mutex;
    Condition _notFull;
    Condition _notEmpty;
    bool _flag;
};
}
#endif

#include "TaskQueue.h"

using namespace wd;
//生产者所在的线程
void TaskQueue::push(Task && task)
{
    MutexLockGuard autoLock(_mutex);
    while(full())
    {
        _notFull.wait();
    }
    _que.push(std::move(task));
    _notEmpty.notify();
}

//消费者所在线程
Task TaskQueue::pop()
{
    MutexLockGuard autoLock(_mutex);
    while(_flag && empty())
    {
        _notEmpty.wait();
    }
    if(_flag){
        Task task=_que.front();
        _que.pop();
        _notFull.notify();
        return task;
    }else{
        return NULL;
    }
}
#if 0
Task TaskQueue::pop()
{
    MutexLockGuard autoLock(_mutex);
    while(_flag && empty())
    {
        _notEmpty.wait();
    }
    if(_flag){
        Task task =_que.front();
        _que.pop();
        _notFull.notify();
        return task;
    }else{
        return NULL;
    }
}
#endif

==TcpConnection:==
 ///=======================================
 /// File:    TcpConnection.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-06 17:15:33
 /// Dream:   Don't forget your dreams!
 /// ======================================

#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>
namespace wd
{
    class EpollPoller;
    class TcpConnection;
    typedef std::shared_ptr<TcpConnection> TcpConnectionPtr;

    class TcpConnection
    :Noncopyable
    ,public std::enable_shared_from_this<TcpConnection>
    {
    public:
        typedef std::function<void(const TcpConnectionPtr &)>TcpConnectionCallback;
        TcpConnection(int sockfd,EpollPoller *loop);
        ~TcpConnection();

        std::string receive();
        void send(const std::string &msg);
        void sendInLoop(const std::string &msg);
        void shutdown();

        std::string toString();
        void setConnectionCallback(TcpConnectionCallback cb);
        void setMessageCallback(TcpConnectionCallback cb);
        void setCloseCallback(TcpConnectionCallback cb);

        void handleConnectionCallback();
        void handleMessageCallback();
        void handleCloseCallback();
    private:
        Socket _sockfd;
        SocketIO _sockIO;
        const InetAddress _localAddr;
        const InetAddress _peerAddr;
        bool _isShutdownWrite;
        EpollPoller * _loop;
        TcpConnectionCallback _onConnectionCb;
        TcpConnectionCallback _onMessageCb;
        TcpConnectionCallback _onCloseCb;

    };
}
#endif

 ///=======================================
 /// File:    TcpConnection.cc
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-07 22:22:22
 /// Dream:   Don't forget your dreams!
 /// ======================================

#include "TcpConnection.h"
#include "EpollPoller.h"
#include <string.h>
#include <stdio.h>

namespace wd
{
TcpConnection::TcpConnection(int sockfd,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::string TcpConnection::receive()
{
    char buf[65536];
    memset(buf,0,sizeof(buf));
    size_t ret =_sockIO.readline(buf,sizeof(buf));
    if(0==ret){
        return std::string();
    }else{
        return std::string(buf);
    }
}

void TcpConnection::send(const std::string &msg)
{
    size_t len=msg.size();
    _sockIO.writen((const char *)&len,sizeof(int));
    _sockIO.writen(msg.c_str(),len);
}

void TcpConnection::shutdown()
{
    if(!_isShutdownWrite)
        _sockfd.shutdownWrite();
    _isShutdownWrite=true;
}

std::string TcpConnection::toString()
{
    char str[100];
    snprintf(str,sizeof(str),"%s:%d->%s:%d"
             ,_localAddr.ip().c_str()
             ,_localAddr.port()
             ,_peerAddr.ip().c_str()
             ,_peerAddr.port());
    return std::string(str);
}

void TcpConnection::setConnectionCallback(TcpConnectionCallback cb)
{
    _onConnectionCb =cb;
}
void TcpConnection::setMessageCallback(TcpConnectionCallback cb)
{
    _onMessageCb =cb;
}
void TcpConnection::setCloseCallback(TcpConnectionCallback cb)
{
    _onCloseCb =cb;
}

void TcpConnection::handleConnectionCallback()
{
    if(_onConnectionCb){
        _onConnectionCb(shared_from_this());
    }
}
void TcpConnection::handleMessageCallback()
{
    if(_onMessageCb){
        _onMessageCb(shared_from_this());
    }
}
void TcpConnection::handleCloseCallback()
{
    if(_onCloseCb){
        _onCloseCb(shared_from_this());
    }
}

void TcpConnection::sendInLoop(const std::string & msg)
{
    _loop->runInLoop(std::bind(&TcpConnection::send,this,msg));
}

}

==TcpServer:==
 ///=======================================
 /// File:    TcpServer.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-06 20:15:21
 /// Dream:   Don't forget your dreams!
 /// ======================================
 
#ifndef __WD_TCPSERVER_H__
#define __WD_TCPSERVER_H__

#include "Acceptor.h"
#include "EpollPoller.h"
#include <string>

using std::string;
namespace wd
{
    class TcpServer
    {
    public:
        typedef EpollPoller::EpollCallback TcpServerCallback;
        TcpServer(const string & ip,unsigned short port);
        TcpServer(unsigned short port);

        void start();
        void stop();
        void setConnectionCallback(TcpServerCallback cb);
        void setMessageCallback(TcpServerCallback cb);
        void setCloseCallback(TcpServerCallback cb);

    private:
        Acceptor _acceptor;
        EpollPoller _poller;

        TcpServerCallback _connectionCallback;
        TcpServerCallback _messageCallback;
        TcpServerCallback _closeCallback;
    };
}
#endif

 ///=======================================
 /// File:    TcpServer.cc
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-07 19:59:37
 /// Dream:   Don't forget your dreams!
 /// ======================================

#include "TcpServer.h"
#include "InetAddress.h"
#include "SocketUtil.h"
#include <iostream>
using namespace std;
namespace wd
{
    TcpServer::TcpServer(const string & ip,unsigned short port)
    :_acceptor(createSocketFd(),InetAddress(ip.c_str(),port))
    ,_poller(_acceptor)
    {}

    void TcpServer::start()
    {
        _acceptor.ready();
        _poller.setConnectionCallback(_connectionCallback);
        _poller.setMessageCallback(_messageCallback);
        _poller.setCloseCallback(_closeCallback);
        _poller.loop();
    }

    void TcpServer::stop()
    {
        _poller.unloop();
    }

    void TcpServer::setConnectionCallback(TcpServerCallback cb)
    {_connectionCallback=cb;}

    void TcpServer::setMessageCallback(TcpServerCallback cb)
    {_messageCallback=cb;}

    void TcpServer::setCloseCallback(TcpServerCallback cb)
    {_closeCallback=cb;}
}

==Thread:==
#ifndef  __WD_THREAD_H__
#define  __WD_THREAD_H__

#include "Noncopyable.h"
#include <pthread.h>
#include <functional>
using std::function;
namespace wd
{
class Thread;
struct ThreadPtr
{
    int _number;
    Thread *_pthread;
};
class Thread
:Noncopyable//此处不可复制,表达语义
{
    using ThreadCallback =function<void()>;
public:
    Thread(ThreadCallback &&cb);
    ~Thread();

    void start(int number);
    void join();

    bool isRunning()const {return _isRunning;}

private:
    static void * threadFunc(void *);//采用静态成员函数,去除this的影响
    pthread_t _pthid;
    bool _isRunning;
    ThreadCallback _cb;
};
}
#endif

#include "Thread.h"
#include <iostream>
using namespace std;
using namespace wd;

__thread int t_number;//与线程存储有关
//右值引用本身取决于其是否有名字,来决定它是左值还是右值

Thread::Thread(ThreadCallback && cb)
:_pthid(0)
,_isRunning(false)
,_cb(std::move(cb))
{
    cout<<"Thread(cb)"<<endl;
}

void Thread::start(int number)
{
    ThreadPtr *threadPtr=new ThreadPtr();
    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();//执行任务
    delete threadPtr;
    return NULL;
}

void Thread::join()
{
    pthread_join(_pthid,NULL);
    _isRunning=false;
}

Thread::~Thread()
{
    if(_isRunning)
    {
        pthread_detach(_pthid);//将运行的线程交给系统托管
        _isRunning=false;
    }
    cout<<"~Thread()"<<endl;
}

==Threadpoll:==
#ifndef __WD_THREADPOLL_H__
#define __WD_THREADPOLL_H__
#include "TaskQueue.h"
#include "Thread.h"
#include <vector>
#include <memory>
#include <functional>
using namespace std;
using std::shared_ptr;
using std::vector;
namespace  wd
{
    class Threadpool
    {
    public:
        using Task=std::function<void()>;
    
        Threadpool(size_t threadNum,size_t queSize)
        :_threadNum(threadNum)
        ,_queSize(queSize)
        ,_taskQue(_queSize)
        ,_isExit(false)
        {
            _threads.reserve(_threadNum);
        }
        
        ~Threadpool();
    
        void start();
        void stop();
        void addTask(Task && task);
    
    private:
        void threadFunc();
        Task getTask();
        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>

using namespace std;
using namespace wd;

void Threadpool::start()
{
    for(size_t idx=0;idx<_threadNum;++idx)
    {
        shared_ptr<Thread>pThread(new Thread(std::bind(&Threadpool::threadFunc,this)));
        _threads.push_back(std::move(pThread));
    }
    int number=0;
    for(auto &pThread:_threads)
    {
        pThread->start(number);
        ++number;
    }
}
void Threadpool::stop()
{
    if(!_isExit)
    {
        while(!_taskQue.empty()){
            ::sleep(1);
            cout<<"Threadpool sleep 1 second!"<<endl;
        }
        _isExit=true;
        cout<<"Threadpool ->stop:_isExit="<<_isExit<<endl;
        _taskQue.wakeup();
        for(auto &pthread:_threads){
            pthread->join();
        }
    }
}

Threadpool::~Threadpool()
{
    if(!_isExit){
        stop();
    }
}
void Threadpool::addTask(Task && task)
{
    _taskQue.push(std::move(task));
}

Task Threadpool::getTask()
{
    return _taskQue.pop();
}

void Threadpool::threadFunc()//线程存储中子线程要做的事情
{
    while(!_isExit)
    {
        Task task=getTask();
            if(task){
                task();//执行任务的时间不确定
            }
    }
}

==Timer:==
 ///=======================================
 /// File:    Timer.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-06 20:00:45
 /// Dream:   Don't forget your dreams!
 /// ======================================

#ifndef __WD_TIMER_H__
#define __WD_TIMER_H__
#include <functional>

namespace wd
{
    class Timer
    {
    public:
        using TimerCallback =std::function<void()>;
        Timer(int initailTime,int intervalTime,TimerCallback && cb);
        ~Timer();
        void start();
        void stop();
    private:
        int _fd;
        int _initialTime;
        int _intervalTime;
        TimerCallback _cb;
        bool _isStarted;
        int createTimerFd();
        void setTimerfd(int initialTime, int intervalTime);
        void handleRead();  
    };
}
#endif

 ///=======================================
 /// File:    Timer.cc
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-07 20:09:14
 /// Dream:   Don't forget your dreams!
 /// ======================================

#include "Timer.h"
#include <unistd.h>
#include <errno.h>
#include <poll.h>
#include <sys/timerfd.h>
#include <iostream>
using namespace std;
using namespace wd;

Timer::Timer(int initialTime,int intervalTime,TimerCallback && cb)
:_fd(createTimerFd())
,_initialTime(initialTime)
,_intervalTime(intervalTime)
,_cb(std::move(cb))
,_isStarted(false)
{}

void Timer::start()
{
    struct pollfd pfd;
    pfd.fd=_fd;
    pfd.events=POLLIN;
    setTimerfd(_initialTime,_intervalTime);
    _isStarted=true;
    while(_isStarted){
        int nready=::poll(&pfd,1,5000);
        if(-1==nready &&errno ==EINTR){
            continue;
        }else if(-1==nready){
            perror(">>>poll error!");
            exit(EXIT_FAILURE);
        }else if(0==nready){
            cout<<">>>poll timeout!"<<endl;
        }else{
            if(pfd.revents & POLLIN){
                handleRead();
                if(_cb){
                    _cb();
                }
            }
        }
    }
}

void Timer::stop()
{
    setTimerfd(0,0);
    if(_isStarted){
        _isStarted=false;
    }
}

Timer::~Timer()
{
    if(_isStarted){
        stop();
    }
}

int Timer::createTimerFd()
{
    int fd=::timerfd_create(CLOCK_REALTIME,0);
    if(-1==fd){
        perror(">>timerfd_create error!");
    }
    return fd;
}

void Timer::setTimerfd(int initialTime,int intervalTime)
{
    struct itimerspec value;
    value.it_value.tv_sec=initialTime;
    value.it_value.tv_nsec=0;
    value.it_interval.tv_sec=intervalTime;
    value.it_interval.tv_nsec=0;
    int ret=::timerfd_settime(_fd,0,&value,NULL);
    if(-1==ret){
        perror(">>>timerfd_settime error!");
    }
}
#if 0
void Timer::handleRead()
{
    uint64_t howmany;
    int ret =::read(_fd,&howmany,sizeof(uint64_t));
    if(ret!=sizeof(uint64_t)){
        perror("read!");
    }
}
#endif


void Timer::handleRead()
{
    uint64_t howmany;
    int ret=::read(_fd,&howmany,sizeof(uint64_t));
    if(ret!=sizeof(uint64_t)){
        perror(">>>read error!");
    }
}

==TimerThread:==
 ///=======================================
 /// File:    TimerThread.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-06 20:07:05
 /// Dream:   Don't forget your dreams!
 /// ======================================

#ifndef __WD_TIMERTHREAD_H__
#define __WD_TIMERTHREAD_H__

#include "Timer.h"
#include "Thread.h"
#include <functional>

namespace wd
{
    class TimerThread
    {
    public:
        using TimerCallback =std::function<void()>;
        TimerThread(int ,int ,TimerCallback && cb);
        ~TimerThread();
        void start();
        void stop();
    private:
        Timer _timer;
        Thread _subThread;
        bool _isStarted;
    };
}
#endif

 ///=======================================
 /// File:    TimerThread.cc
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-07 17:12:51
 /// Dream:   Don't forget your dreams!
 /// ======================================

#include "TimerThread.h"

using namespace wd;

TimerThread::TimerThread(int initialTime,int intervalTime,TimerCallback &&cb)
:_timer(initialTime,intervalTime,std::move(cb))
,_subThread(std::bind(&Timer::start,&_timer))
,_isStarted(false)
{}

void TimerThread::start()
{
    _subThread.start(0);
    _isStarted =true;
}

void TimerThread::stop()
{
    if(_isStarted){
        _timer.stop();
        _subThread.join();
        _isStarted=false;
    }
}

TimerThread::~TimerThread()
{
    if(_isStarted)
        stop();
}

==WebPage:==
 ///=======================================
 /// File:    WebPage.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-23 10:35:35
 /// Dream:   Don't forget your dreams!
 /// ======================================

#ifndef __WEBPAGE_H__
#define __WEBPAGE_H__
#include "ConFiguration.h"
#include "WordSegmentation.h"
#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <set>

using namespace std;

class WebPage
{
public:
    WebPage(string doc,Configuration & config,WordSegmentation & jieba);
    int getDocId();
    const string & getDoc() const;
    map<string,int>& getWordMap();//获取文档的词频统计map
    const string & getTitle()const;
    const string & getUrl() const;

    WebPage(const WebPage &rhs);
    WebPage(WebPage && rhs);
    WebPage & operator =(WebPage && rhs);
    WebPage & operator=(const WebPage & rhs);
    string _docSummary;

private:
    void processDoc(string & doc ,WordSegmentation&);
    string _doc;
    int _docId;
    string _docTitle;
    string _docUrl;
    string _docContent;
    map<string,int> _wordsMap;
    Configuration & _conf;
};
#endif

 ///=======================================
 /// File:    WebPage.cc
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-25 10:35:57
 /// Dream:   Don't forget your dreams!
 /// ======================================

#include "WebPage.h"
#include <stdlib.h>
#include <iostream>
#include <utility>
#include <algorithm>
#include <functional>
using namespace std;
bool cmp(pair<string,int> a,pair<string,int> b)
{
    if(a.second != b.second){
        return a.second>b.second;
    }else{
        return a.first.size()<b.first.size();
    }
}

const string & WebPage::getUrl() const
{
    return _docUrl;
}
const string & WebPage::getTitle() const
{
    return _docTitle;
}

WebPage::WebPage(string doc,Configuration & config,WordSegmentation & jieba)
:_doc(std::move(doc))
,_conf(config)
{
    auto n1 =_doc.find("<docid>");//在格式化字符串取得id
    auto cit1 =_doc.begin()+n1+7;
    auto n2 =_doc.find("</docid>");//在格式化字符串取得id
    auto cit2 =_doc.begin()+n1+n2;
    string docId(cit1,cit2);
    _docId =::atoi(docId.c_str());

    n1 =_doc.find("<url>");//在格式化字符串取得url
    cit1 =_doc.begin()+n1+5;
    n2 =_doc.find("</url>");//在格式化字符串取得url
    cit2 =_doc.begin()+n1+n2;
    _docUrl.insert(_docUrl.end(),cit1,cit2);

    n1 =_doc.find("<title>");//在格式化字符串取得title
    n2 =_doc.find("</title>");
    cit1 =_doc.begin()+n1+7;
    cit2 =_doc.begin()+n2;
    _docTitle.insert(_docTitle.end(),cit1,cit2);

    n1 =_doc.find("<content>");//在格式化字符串取得content
    n2 =_doc.find("</content>");
    cit1 =_doc.begin()+n1+9;
    cit2 =_doc.begin()+n2;
    _docTitle.insert(_docContent.end(),cit1,cit2);
    processDoc(_docContent,jieba);
}

void WebPage::processDoc(string & doc,WordSegmentation & jieba)
{
    vector<string> results =jieba.Cut(doc);
    for(auto myresult:results)
    {
        auto cit =_wordsMap.find(myresult);
        if(cit ==_wordsMap.end())
            _wordsMap.insert(std::make_pair(myresult,1));
        else
            ++cit->second;
    }
}

int WebPage::getDocId()
{
    return _docId;
}

const string & WebPage::getDoc() const
{
    return _doc;
}

map<string ,int> & WebPage::getWordsMap()
{
    return _wordsMap;
}
WebPage & WebPage::operator=(WebPage && rhs)
{
    _doc =std::move(rhs._doc);
    _docId =std::move(rhs._docId);
    _docTitle =std::move(rhs._docTitle);
    _docUrl=std::move(rhs._docUrl);
    _docSummary=std::move(rhs._docSummary);
    _docContent=std::move(rhs._docContent);
    _wordsMap =std::move(rhs._wordsMap);
    _conf =rhs._conf;
    return *this;
}

WebPage & WebPage::operator=(const WebPage & rhs)
{
    _doc =rhs._doc;
    _docId =rhs._docId;
    _docTitle=rhs._docTitle;
    _docUrl=rhs._docUrl;
    _docSummary=rhs._docSummary;
    _docContent=rhs._docContent;
    _wordsMap=rhs._wordsMap;
    _conf=rhs._conf;
    return *this;
}

WebPage::WebPage(const WebPage & rhs)
:_conf(rhs._conf)
{
    _doc =rhs._doc;
    _docId =rhs._docId;
    _docTitle=rhs._docTitle;
    _docUrl=rhs._docUrl;
    _docSummary=rhs._docSummary;
    _docContent=rhs._docContent;
    _wordsMap=rhs._wordsMap;
}

WebPage::WebPage(WebPage && rhs)
:_conf(std::ref((rhs._conf)))
{
    _doc =std::move(rhs._doc);
    _docId=std::move(rhs._docId);
    _docUrl=std::move(rhs._docUrl);
    _docTitle=std::move(rhs._docTitle);
    _docContent=std::move(rhs._docContent);
    _docSummary=std::move(rhs._docSummary);
    _wordsMap=std::move(rhs._wordsMap);
}

==WordQuery:==
 ///=======================================
 /// File:    WordQuery.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-23 10:54:39
 /// Dream:   Don't forget your dreams!
 /// ======================================

#ifndef __WORDQUERY_H__
#define __WORDQUERY_H__
#include "ConFiguration.h"
#include "WordSegmentation.h"
#include "WebPage.h"
#include "TcpConnection.h"
using namespace std;
#include <unordered_map>
#include <string>
#include <vector>
#include <iostream>
#include <utility>
namespace wd
{
    class WordQuery
    {
    public:
        WordQuery(Configuration & conf);
        void doQuery(string &str,TcpConnnectionPtr & conn);
    private:
        void loadLibary();
        map<string,int>getQueryWordsMap(vector<string> & queryWords);
        vector<pair<string,double>>getQueryWordsWeightVector(map<string,int>&);
        bool exexuteQuery(const vector<pair<string,double>>&,vector<pair<int,vector<double>>>&); 
        string createJson(vector<pair<int,double>>&);
        string returnNoAnswer();
        int sumApperaance(const string& word);
        void processQuery(string& line);
        Configuration & _conf;
        WordSegmentation _jieba;
        unordered map<int,WebPage> _pageLib;
        unordered map<int,pair<int,int>> _offsetLib;
        unordered map<string,set<pair<int,double>>> _inverIndexTable;
    };
};
#endif

 ///=======================================
 /// File:    WordQuery.cc
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-23 10:54:39
 /// Dream:   Don't forget your dreams!
 /// ======================================
#include "WordQuery.h"
#include "TcpConnection.h"
#include "WebPage.h"
#include "json/json.h"
#include <math.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <map>
#include <utility>
#include <cctype>
#define DEBUG 0
using namespace std;
using namespace wd;

WordQuery::WordQuery(Configuration& conf)
    :_conf(conf)
    ,_jieba()
{
    loadLibary();
}
void WordQuery::loadLibary()
{
    map<string,string>& config = _conf.getConfigMap();
    string pageLibPath = config["myPageLib"];
    string offsetLibPath = config["myOffsetLib"];
    string indexLibPath = config["myIndexLib"];
    ifstream ifsPage(pageLibPath);
    ifstream ifsOffset(offsetLibPath);
    ifstream ifsIndex(indexLibPath);
    if(!ifsPage || !ifsOffset ||!ifsIndex)
    {
        cout << "loadLibary file open error" << endl;
        return;
    }
    int offset,len;
    while(ifsOffset >> offset)
    {
        string doc = "";
        ifsOffset >> len;
        ifsPage.seekg(offset,std::ios_base::beg);
        int left = len;
        while(left > 0)
        {
            char tmp;
            ifsPage >> tmp;
            --left;
            doc += tmp;
        }
        WebPage tmpPage(doc,_conf,_jieba);
        int id = tmpPage.getDocId();
        pair<int,int> myoffset = std::make_pair(offset,len);
        _offsetLib.insert(std::make_pair(id,myoffset));
        _pageLib.insert(std::make_pair(id,tmpPage));
    }
    string indexLine;
    while(std::getline(ifsIndex,indexLine))
    {
        istringstream iss(indexLine);
        string word;
        iss >> word;
        int key;
        double value;
        while(iss >> key)
        {
            iss >> value;
            auto cit = _inverIndexTable.find(word);
            if(cit == _inverIndexTable.end()){
                set<pair<int,double>> tmp;
                tmp.insert(std::make_pair(key,value));
                _inverIndexTable.insert(std::make_pair(word,tmp));
            }else{
                cit->second.insert(std::make_pair(key,value));
            }
        }
    }
}
void WordQuery::processQuery(string& line)
{
    auto cit = line.begin();
    for(;cit != line.end(); ++cit)
    {
        if(isspace(*cit)){
            cit = line.erase(cit);
            --cit;
        }
    }
}
void WordQuery::doQuery(string& str,TcpConnectionPtr& conn)
{
#if 0  //DEBUG
    cout << "In WordQuery:: doQuery" << endl;
#endif
    processQuery(str);   //将str中的空白符去除
    vector<string> queryWords = _jieba.Cut(str);
    for(auto word:queryWords)
        cout << ">>> cut word is " << word << endl;
    map<string,int> processedQueryWords = getQueryWordsMap(queryWords);    //返回处理过的查询词(合并相同的查询词)
    vector<pair<string,double>> queryWordsWeightVec = getQueryWordsWeightVector(processedQueryWords);
#if 0 //DEBUG
    for(auto a:queryWordsWeightVec)
    {
        cout << ">>>> in queryWordsWeightVec   " << a.first << " " << a.second << endl;
    }
#endif
    string firstQueryWord = queryWordsWeightVec.begin()->first;
    double moduleQuery = 0;
    for(auto queryPair:queryWordsWeightVec)
            moduleQuery += queryPair.second * queryPair.second;
    moduleQuery = ::sqrt(moduleQuery);
#if DEBUG
    cout << ">>>>moduleQuery is " << moduleQuery << endl;
#endif
    vector<pair<int,vector<double>>> resultVec;
    bool flag = executeQuery(queryWordsWeightVec,resultVec);
    if(flag){
#if DEBUG
        cout << "flag is true" << endl;
#endif
        vector<pair<int,double>> cosinRes;
        for(auto myres:resultVec)  //生成摘要并计算模
        {
            double moduleRes = 0;
            double sum = 0;
            int docId = myres.first;
            auto pageIter = _pageLib.find(docId);
            WebPage& mypage = pageIter->second;
            string pagedoc = mypage.getDoc();   //一篇pagedoc就是一行
            int  pos = pagedoc.find(firstQueryWord);
            string docline(pagedoc.begin() + pos -50,pagedoc.begin() + pos +50);
            mypage._docSummary = docline;
#if DEBUG
            cout << ">>>> SUMMARY IS " << docline << endl;
#endif
            for(size_t i=0;i<myres.second.size();++i)
            {
                sum += myres.second[i]*(queryWordsWeightVec[i].second);
                moduleRes += (myres.second)[i] * (myres.second)[i];
            }
            moduleRes = ::sqrt(moduleRes);
            cosinRes.push_back(std::make_pair(docId,sum/(moduleRes * moduleQuery)));
        }
        string jsonResult = createJson(cosinRes);
        conn->sendInLoop(jsonResult);
#if DEBUG
        cout << ">>>JsonResult is " << jsonResult << endl;
#endif
    }else{
#if DEBUG
        cout << "flag is false" << endl;
#endif 
        string jsonResult = returnNoAnswer();
        conn->sendInLoop(jsonResult);
    }
}
string WordQuery::returnNoAnswer()
{
    Json::FastWriter writerinfo;
    Json::Value obj,new_item;
    new_item["标题"] = "404,not found";
    new_item["摘要"] = "亲,I cannot find what you want. What a pity";
    obj.append(new_item);
    string strEmail = writerinfo.write(obj);
    return strEmail;
}
bool cmp(pair<int,double> a,pair<int,double> b)
{
    if(a.second!=b.second)
        return a.second > b.second;
    else
        return a.first <= b.first ;
}
string WordQuery::createJson(vector<pair<int,double>>& resultVec)
{
    std::sort(resultVec.begin(),resultVec.end(),cmp);
    Json::FastWriter writerinfo;
    Json::Value arrayObj;
    auto cit = resultVec.begin();
    for(;cit != resultVec.begin() + 10&& cit != resultVec.end(); ++cit)
    {
        auto pageIter = _pageLib.find(cit->first);
        WebPage& mypage = pageIter->second;
        Json::Value new_item;
        new_item["标题"] =  mypage.getTitle();
        new_item["url"] = mypage.getUrl();
        new_item["摘要"] = mypage._docSummary;
        arrayObj.append(new_item);
    }
    string strEmail = writerinfo.write(arrayObj);
    return strEmail;
}
bool WordQuery::executeQuery(const vector<pair<string,double>>& queryWordsWeightVec,vector<pair<int,vector<double>>>& resultVec)
{
#if 1                  //找到文章Id的集合
    auto iter = queryWordsWeightVec.begin();
    auto cit = _inverIndexTable.find(iter->first);
    set<int> docIdGather;
    if(cit == _inverIndexTable.end())
        return false;
    set<pair<int,double>> articleGather = cit->second;   //取出第一个查询词的所有文章
    for(auto oneArticle:articleGather)  //对查询词中的文章进行查询,若其他查询词也在其中,则为结果文章
    {
        bool flag = true;
        int docId = oneArticle.first;
        auto pageIter = _pageLib.find(docId);
        WebPage& tmp = pageIter->second;
        map<string,int>& wordsMap = tmp.getWordsMap();
        for(auto myQueryWord: queryWordsWeightVec)
        {
            auto queryIter = wordsMap.find(myQueryWord.first);
            if(queryIter == wordsMap.end()){    //如果有一篇文章中不包含所有查询词,就返回false
                flag = false;  
            }
        }
        if(flag){
            vector<double> weightVec;
            docIdGather.insert(docId);
        }
    }
#endif
    if(docIdGather.size() == 0)
        return false;
    else{
        for(auto docId: docIdGather)   //查找每一篇文章中对应查询词的权重,构成向量
        {
            vector<double> tmp;
            for(auto myQueryWord:queryWordsWeightVec)
            {
                auto citer = _inverIndexTable.find(myQueryWord.first);
                for(auto mypair:citer->second)
                {
                    if(mypair.first == docId){
                        tmp.push_back(mypair.second);
                        break;
                    }
                }
            }
            resultVec.push_back(std::make_pair(docId,tmp));
        }
        return true;
    }
}


vector<pair<string,double> > WordQuery::getQueryWordsWeightVector(map<string,int>& processedQueryWords)
{
#if DEBUG 
    cout << "In WordQuery getQueryWordsWeightVector() " << endl;
#endif
    vector<pair<string,double>> tmp;
    double w_total = 0;
    for(auto& mypair:processedQueryWords)
    {
        int tf = mypair.second;
        int DF = sumApperaance(mypair.first) + 1;
        int N = _pageLib.size() + 1;
#if DEBUG //DEBUG
        cout << " >> N is " << N << endl;
        cout << ">>>> DF is " << DF << endl;
#endif 
        double w = (double)tf * :: log10(N/DF)/ ::log10(2);
#if DEBUG //DEBUG
        cout << ">>>>> w is " << w << endl;
#endif 
        w_total += w*w;
        tmp.push_back(std::make_pair(mypair.first,w));
    }
#if DEBUG
    cout << ">>> w_total is " << w_total << endl;
#endif
    if(w_total)
        for(auto& mypair:tmp)     //归一化处理
        {
            mypair.second /= (::sqrt(w_total));
#if DEBUG
            cout << "In the tmpVec w is " << mypair.second << endl;
#endif
        }
    return tmp;
}
int WordQuery::sumApperaance(const string& word)
{
#if DEBUG
    cout << "In sumApperaance" << endl;
#endif
    int cnt = 0;
    for(auto& mypage:_pageLib)
    {
        map<string,int>& oneArticle = mypage.second.getWordsMap();
        auto cit = oneArticle.find(word);
        if(cit != oneArticle.end())
            ++cnt;
    }
    return cnt;
}
map<string,int> WordQuery::getQueryWordsMap(vector<string>& queryWords)
{
#if DEBUG //DEBUG
    cout << "In the getQueryWordsMap" << endl;
#endif
    map<string,int> tmp;
    for(auto word:queryWords)
    {
        auto cit = tmp.find(word);
        if(cit == tmp.end())
        {
            tmp.insert(std::make_pair(word,1));
        }else
            ++cit->second;
    }
#if DEBUG //DEBUG
    for(auto mytmp:tmp)
        cout << ">>> In tmp Map " << mytmp.first << " " << mytmp.second << endl;
#endif
    return tmp;
}

==WordQueryServer:==
 ///=======================================
 /// File:    WordQueryServer.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-25 10:14:30
 /// Dream:   Don't forget your dreams!
 /// ======================================

#ifndef __WORDQUERYSERVER_H__
#define __WORDQUERYSERVER_H__
#include "TcpServer.h"
#include "Condition.h"
#include "WordQuery.h"
#include "Threadpool.h"
#include "TcpConnection.h"
#include <iostream>
#include <utility>
using namespace std;
namespace wd
{
    class WordQueryServer
    {
    public:
        WordQueryServer(const string & filename);
        void start();
    private:
        void onConnection(const TcpConnnectionPtr & conn);
        void onMessage(const TcpConnnectionPtr & conn);
        void onClose(const TcpConnectionPtr & conn);
        void doTaskThread(const TcpConnectionPtr & conn,const string & msg);
    private:
        Configuration _conf;
        WordQuery _wordQuery;
        TcpServer _tcpServer;
        Threadpool _pool;
    };
}
#endif

 ///=======================================
 /// File:    WordQueryServer.cc
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-25 10:14:30
 /// Dream:   Don't forget your dreams!
 /// ======================================
#include "WordQueryServer.h" 
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <functional>
#include <string>
#define THREADNUM 4
#define QUESIZE 10
using std::cout;
using std::endl;
using std::string;
using namespace wd;
WordQueryServer::WordQueryServer(const string& filename)
    :_conf(filename)
    ,_wordQuery(_conf)
    ,_tcpServer(_conf.getIp(),_conf.getPort())
    ,_pool(THREADNUM,QUESIZE)
{}

void WordQueryServer::onConnection(const TcpConnectionPtr& conn)
{
    cout << conn->toString() << endl;
    conn->send("hello,welcome to Chat Server.\r\n");
}
void WordQueryServer::onMessage(const TcpConnectionPtr& conn)
{
    string s(conn->receive());
    _pool.addTask(std::bind(&WordQuery::doQuery,&_wordQuery,s,conn));
    cout << "> add task to threadpool" << endl;
}
void WordQueryServer::onClose(const TcpConnectionPtr& conn)
{
    ::printf("%s close\n",conn->toString().c_str());
}
void WordQueryServer::start()
{
    _pool.start();
    _tcpServer.setConnectionCallback(std::bind(&WordQueryServer::onConnection,this,std::placeholders::_1));
    _tcpServer.setMessageCallback(std::bind(&WordQueryServer::onMessage,this,std::placeholders::_1));
    _tcpServer.setCloseCallback(std::bind(&WordQueryServer::onClose,this,std::placeholders::_1));
    _tcpServer.start();
}


==WordSegmentation:==
 ///=======================================
 /// File:    WordSegmentation.h
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-23 10:45:14
 /// Dream:   Don't forget your dreams!
 /// ======================================

#ifndef __WORDSEGMENTATIAON_H__
#define __WORDSEGMENTATIAON_H__
#include "/home/wtp/search/cppjieba/include/cppjieba/Jieba.hpp"
#include <string>
#include <vector>
using namespace std;
const char * const DICT_PATH="/home/wtp/search/cppjieba/dict/jieba.dict.utf8";
const char * const HMM_PATH="/home/wtp/search/cppjieba/dict/hmm_model.utf8";
const char * const USER_DICT_PATH="/home/wtp/search/cppjieba/dict/user.dict.utf8";
const char * const IDF_PATH="/home/wtp/search/cppjieba/dict/idf.utf8";
const char * const STOP_WORD_PATH="/home/wtp/search/cppjieba/dict/stop_words.utf8";

class WordSegmentation
{
public:
    WordSegmentation()
    :_jieba(DICT_PATH,HMM_PATH,USER_DICT_PATH,IDF_PATH,STOP_WORD_PATH)
    {}
    vector<string> Cut(string & sentence)
    {
        vector<string>tmp;
        _jieba.Cut(sentence,tmp);
        return tmp;
    }
private:
    cppjieba::Jieba _jieba;
};
#endif

==Main:==
 ///=======================================
 /// File:    main.cc
 /// Author:  wtptorres(1584292712@qq.com)
 /// Date:    2019-06-07 21:09:32
 /// Dream:   Don't forget your dreams!
 /// ======================================
#include "WordQueryServer.h"
#include "ConFiguration.h"
#include "CacheManger.h"
#include "TimerThread.h"
#include <iostream>
#include <functional>
using namespace std;
using namespace wd;

int main()
{
    WordQueryServer wordQueryServer("./conf/configure.txt");
    wordQueryServer.start();
    return 0;
}


小结:

(1)已经实现项目需求,中文和英文单词都能查询

(2)相比spellcorrect的众多bug,这一次几乎没有测试出bug

(3)由于时间问题,没有导入php前端进行测试,后期考虑用户界面及Reddish内存(mysql)

(4)陈硕的《linux多线程服务端编程》使用linux接口(timerfd),没用posix接口(eventfd)

转载于:https://www.cnblogs.com/wtptorres/p/11084229.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值