////// @file Data.h/// @brief 套接字发送接收的封装/// @author guozhiming/// @date 2007-05-21///#ifndef __DATA__#define __DATA__#include "def.h"#include "RecvMessThread.h"#include "SendMessThread.h"class G_RecvMessThread;class G_SendMessThread;class G_Data{    public:        /// @brief 构造函数        G_Data(G_RecvMessThread *recvMessThread);        G_Data();        /// @brief 析构函数        ~G_Data();        /// @brief 接收数据并存到缓冲池中        ///        /// @param nSocket  套接字        ///        /// @return         如果收到数据返回成功 , 如果client关闭返回false        bool recvData(int nSocket);        /// @brief 发送数据        ///        /// @param nSocket 套接字        /// @param pData 数据包        /// @param nLen 数据包长度        ///        /// @return        int sendData(int nSocket , const void *pStr , unsigned int nLen);    private:        /// @brief 发送数据        ///        /// @param nSocket  套接字        /// @param ptr      发送数据        /// @param nLen     数据长度        ///        /// @return          发送数据长度        int sendn(int nSocket , const void *pStr , unsigned int nLen);        /// @brief 从套接口接受数据        ///        /// @param nSocket  套接口        /// @param pStr     存放数据        /// @param nLen     长度        ///        /// @return         返回接受数据长度        int recvn(int nSocket , void *pStr , unsigned int nLen);        /// @brief 对数据进行打包        ///        /// @param pStr     输入数据        /// @param nLen     数据包长度        /// @param pBuffer  输出数据        ///        /// @return        int packet(const void *pStr , unsigned int nLen , char *pBuffer);        /// @brief 对数据进行解包        ///        /// @param in 输入数据        /// @param fromLen 从什么地方开始        /// @param nLen  数据长度        /// @param out 输出数据        ///        //void unPacket(const char *in , unsigned int fromLen , unsigned int nLen , char *out);        void unPacket(const void *in , unsigned int fromLen , unsigned int nLen , void *out);        /// @brief 返回数据包大小        ///        /// @param pData 数据包        ///        /// @return  包的大小        int packetSize(const char *pStr);        G_RecvMessThread *g_recvMessThread;        /// @brief 数据包大小        static const unsigned int G_MAXDATABUFFSIZE = 65535;  //这个够大。。        /// @brief 数据包包头大小        static const unsigned int G_PHLEN = sizeof(unsigned int);};#endif

#include "Data.h"G_Data::G_Data(G_RecvMessThread *recvMessThread) : g_recvMessThread(recvMessThread){}G_Data::G_Data(){}G_Data::~G_Data(){}//封装了发送函数。。。一定要这么做吗?以前看书,书上也这么干,忘了原因。int G_Data::sendn(int nSocket , const void *pStr , unsigned int nLen){    int n = nLen , nRet;    char *str = (char*)pStr;    while(n > 0)    {        nRet = send(nSocket , str , n , MSG_NOSIGNAL);        if(nRet <= 0)        {            if(errno == EINTR)            {                continue;            }            return -1;        }        n -= nRet;        str += nRet;    }    return (nLen - n);}//用epoll通知的方式,也需要这样吗?int G_Data::recvn(int nSocket , void *pStr , unsigned int nLen){    int n = nLen;    char *str = (char*)pStr;    while(n > 0)    {        int nRet = recv(nSocket , str , n , MSG_NOSIGNAL);        if(nRet <= 0)        {            if(errno == EINTR)            {                continue;            }            break;        }        n -= nRet;        str += nRet;    }    return (nLen - n);}int G_Data::packet(const void *pStr , unsigned int nLen , char *pBuffer){    bcopy(pStr , &pBuffer[G_PHLEN] , nLen);    *(unsigned int *)pBuffer = nLen;    return (nLen + G_PHLEN);}int G_Data::packetSize(const char *pStr){    return (*(unsigned int*)pStr);}void G_Data::unPacket(const void *in , unsigned int fromLen , unsigned int nLen , void *out){    bcopy(&((char*)in)[G_PHLEN+fromLen] , out , nLen);}int G_Data::sendData(int nSocket , const void *pStr , unsigned int nLen){    char pBuffer[G_MAXDATABUFFSIZE];    bzero(pBuffer , sizeof(pBuffer));    if(!pStr)    {        return -1;    }    int nSize = packet(pStr , nLen , pBuffer);    int nRet = sendn(nSocket , pBuffer , nSize);    return nRet;}bool G_Data::recvData(int nSocket){    char pBuffer[G_MAXDATABUFFSIZE]; char pStr[G_MAXDATABUFFSIZE];    bzero(pBuffer , sizeof(pBuffer));    bzero(pStr , sizeof(pStr));    int fromLen = 0 , n;    int nSize = recvn(nSocket , pBuffer , sizeof(pBuffer));    ///返回接收数据大小    if(nSize <= 0)    {        return false;    }                              while(1)    {        n = packetSize(&pBuffer[fromLen]);   /// 返回数据真正大小        unPacket(pBuffer , fromLen , n , pStr);    ///把真正数据存放到pStr中        g_recvMessThread->pushData((std::string)pStr);          ///放到数据池队列中            //收到的数据放入队列中,这是ok的。recv要开那么多线程吗?recv是阻塞的?        n += sizeof(unsigned int);        fromLen += n;        if(fromLen == nSize)        {            break;    ///如果数据都取完了退出循环        }    }    return true;}

////// @file SendMessThread.h/// @brief 发送消息线程 server->client/// @author guozhiming/// @date 2007-05-18///#ifndef __G_SENDMESSTHREAD__#define __G_SENDMESSTHREAD__#include "def.h"#include "Thread.h"#include "ThreadPool.h"#include "Queue.h"#include "Data.h"class G_Data;class G_SendMessThread : public G_Thread{    public:        /// @brief 构造函数        G_SendMessThread();        /// @brief 析构函数        ~G_SendMessThread();        void Run();        void addEpoll(int nSocket);  //这里也开了epoll,接受和发送都开。但是recv开了那么多线程,每个都开epoll        void modEpoll(int nSocket);        //void delEpoll(int nSocket);        int sendMessage(int nSocket , const void *pStr);    private:                                  /// @brief epoll_create 返回文件描述符        int epfd;        struct epoll_event event[100] , ev;        /// @brief 存放套接字和数据multimap        multimap
g_sockDataMap;//用标准c++类。只有那个queue封装了mutex,有必要吗? /// @brief multimap插入值 typedef pair
g_mapPair; /// @brief 数据发送对象 G_Data *g_data;};#endif

#include "Log.h"#include "SendMessThread.h"G_SendMessThread::G_SendMessThread(){    bzero(&ev , sizeof(struct epoll_event));    epfd = epoll_create(256);    g_data = new G_Data();}G_SendMessThread::~G_SendMessThread(){    close(epfd);    if(g_data)    {        delete g_data;        g_data = NULL;    }}void G_SendMessThread::addEpoll(int nSocket){    ev.data.fd = nSocket;    ev.events = EPOLLOUT | EPOLLERR;//这里加err。。。。    epoll_ctl(epfd , EPOLL_CTL_ADD , nSocket , &ev);}void G_SendMessThread::modEpoll(int nSocket){    ev.data.fd = nSocket;    ev.events = EPOLLOUT | EPOLLERR;    epoll_ctl(epfd , EPOLL_CTL_MOD , nSocket , &ev);}/*void G_SendMessThread::delEpoll(int nSocket){    ev.data.fd = nSocket;    epoll_ctl(epfd , EPOLL_CTL_DEL , nSocket , &ev);}*/int G_SendMessThread::sendMessage(int nSocket , const void *pStr){    char *str = (char*)pStr;    g_sockDataMap.insert(g_mapPair(nSocket , (std::string)str));      ///把套接口和数据插入map中}void G_SendMessThread::Run(){    multimap
::iterator map_interator; int nfds , i , sock; std::string buffer; while(1) { nfds = epoll_wait(epfd , event , 100 , 500); for(i=0; i
sendData(sock , (void*)map_interator->second.c_str() , strlen(map_interator->second.c_str())); g_sockDataMap.erase(map_interator); } usleep(100); } } }}

////// @file Server.h/// @brief 服务器框架基类/// @author guozhiming/// @date 2007-05-24///#ifndef __SERVER__#define __SERVER__#include "def.h"class G_Server{    public:        /// @brief 析构函数        virtual ~G_Server();                 /// @brief 初始化服务器程序字类需要继承这个函数        ///        /// @return        virtual bool init();        /// @brief 结束服务器程序回收资源    //  virtual void final() = 0;    protected:        /// @brief 构造函数        G_Server();    private:        static G_Server *instance ;};#endif
#include "Server.h"#include "Log.h"G_Server *G_Server::instance = NULL;static void ctrlcHandle(int signum){    debug_output("ctrl-c signal .....\n");}G_Server::G_Server(){    instance = this;}G_Server::~G_Server(){}bool G_Server::init(){    debug_output("%s\n" , __PRETTY_FUNCTION__);    ///定义ctrl-c信号    struct sigaction act;    act.sa_handler = ctrlcHandle;      sigemptyset(&act.sa_mask);    act.sa_flags = 0;    sigaction(SIGINT , &act , NULL);//屏蔽这个信号。。就做了这么一件事。。这么坑。}