当前位置: 首页 > news >正文

无锡制作网站公司南通网站建设计划书

无锡制作网站公司,南通网站建设计划书,网站快速推广,学校vi设计案例http://blog.csdn.net/zhuxiaoping54532/article/details/56494313处理大并发之一对epoll的理解#xff0c;epoll客户端服务端代码序言#xff1a;该博客是一系列的博客#xff0c;首先从最基础的epoll说起#xff0c;然后研究libevent源码及使用方法#xff0c;最后研究n…http://blog.csdn.net/zhuxiaoping54532/article/details/56494313处理大并发之一对epoll的理解epoll客户端服务端代码序言该博客是一系列的博客首先从最基础的epoll说起然后研究libevent源码及使用方法最后研究nginx和node.js关于select,poll这里不做说明只说明其相对于epoll的不足其实select和poll我也没用过因为我选择了epoll。说起epoll做过大并发的估计都不陌生之前做了个STB的工具用的就是epoll处理并发测试1.5W的并发非简单的发消息包括多个服务端和客户端的处理是通过的epoll的功能强大让我有一定的体会在nginx和node.js中利用的就是libevent而libevent使用的就是epoll如果系统不支持epoll会选择最佳的方式(select,poll或kqueue中的一种)。基础资料epoll名词解释看下百科名片是怎么解释epoll的吧http://baike.baidu.com/view/1385104.htmepoll是Linux内核为处理大批量句柄而作了改进的poll是Linux下多路复用IO接口select/poll的增强版本它能显著减少程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率。关于具体的说明可以参考网上资料我这里罗列下epoll相对于其他多路复用机制select,poll的优点吧epoll优点1. 支持一个进程打开大数目的socket描述符。2. IO效率不随FD数目增加而线性下降传统的select/poll每次调用都会线性扫描全部的集合导致效率呈现线性下降。3. 使用mmap加速内核与用户空间的消息传递。无论是select,poll还是epoll都需要内核把FD消息通知给用户空间如何避免不必要的内存拷贝就很重要在这点上epoll是通过内核于用户空间mmap同一块内存实现的。select和poll的缺点1. 每次调用时要重复地从用户态读入参数。2. 每次调用时要重复地扫描文件描述符。3. 每次在调用开始时要把当前进程放入各个文件描述符的等待队列。在调用结束后,又把进程从各个等待队列中删除。分析libevent的时候发现一个博客介绍epoll的不错网址是http://blog.csdn.net/sparkliang/article/details/4770655epoll用的的数据结构和函数数据结构 typedef union epoll_data {                 void *ptr;                 int fd;                 __uint32_t u32;                 __uint64_t u64;         } epoll_data_t;         struct epoll_event {                 __uint32_t events;      /* epoll events */                 epoll_data_t data;      /* user data variable */         }; 结构体epoll_event 被用于注册所感兴趣的事件和回传所发生待处理的事件. 其中epoll_data 联合体用来保存触发事件的某个文件描述符相关的数据. 例如一个client连接到服务器服务器通过调用accept函数可以得到于这个client对应的socket文件描述符可以把这文件描述符赋给epoll_data的fd字段以便后面的读写操作在这个文件描述符上进行。epoll_event 结构体的events字段是表示感兴趣的事件和被触发的事件可能的取值为 EPOLLIN 表示对应的文件描述符可以读 EPOLLOUT表示对应的文件描述符可以写 EPOLLPRI表示对应的文件描述符有紧急的数据可读 EPOLLERR表示对应的文件描述符发生错误 EPOLLHUP表示对应的文件描述符被挂断 EPOLLET表示对应的文件描述符有事件发生 ET和LT模式LT(level triggered)是缺省的工作方式并且同时支持block和no-block socket.在这种做法中内核告诉你一个文件描述符是否就绪了然后你可以对这个就绪的fd进行IO操作。如果你不作任何操作内核还是会继续通知你的所以这种模式编程出错误可能性要小一点。传统的select/poll都是这种模型的代表。ET (edge-triggered)是高速工作方式只支持no-block socket。在这种模式下当描述符从未就绪变为就绪时内核通过epoll告诉你。然后它会假设你知道文件描述符已经就绪并且不会再为那个文件描述符发送更多的就绪通知直到你做了某些操作导致那个文件描述符不再为就绪状态了比如你在发送接收或者接收请求或者发送接收的数据少于一定量时导致了一个EWOULDBLOCK 错误。但是请注意如果一直不对这个fd作IO操作从而导致它再次变成未就绪内核不会发送更多的通知(only once)不过在TCP协议中ET模式的加速效用仍需要更多的benchmark确认。ET和LT的区别在于LT事件不会丢弃而是只要读buffer里面有数据可以让用户读则不断的通知你。而ET则只在事件发生之时通知。可以简单理解为LT是水平触发而ET则为边缘触发。ET模式仅当状态发生变化的时候才获得通知,这里所谓的状态的变化并不包括缓冲区中还有未处理的数据,也就是说,如果要采用ET模式,需要一直read/write直到出错为止,很多人反映为什么采用ET模式只接收了一部分数据就再也得不到通知了,大多因为这样;而LT模式是只要有数据没有处理就会一直通知下去的.函数[cpp] view plain copy1. int epoll_create(int size);  2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);  3. int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);  详解1. int epoll_create(int size);创建一个epoll的句柄size用来告诉内核这个监听的数目一共有多大。需要注意的是当创建好epoll句柄后它就是会占用一个fd值在linux下如果查看/proc/进程id/fd/是能够看到这个fd的所以在使用完epoll后必须调用close()关闭否则可能导致fd被耗尽。2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);epoll的事件注册函数它不同与select()是在监听事件时告诉内核要监听什么类型的事件而是在这里先注册要监听的事件类型。第一个参数是epoll_create()的返回值第二个参数表示动作用三个宏来表示EPOLL_CTL_ADD注册新的fd到epfd中EPOLL_CTL_MOD修改已经注册的fd的监听事件EPOLL_CTL_DEL从epfd中删除一个fd第三个参数是需要监听的fd第四个参数是告诉内核需要监听什么事3. int epoll_wait(int epfd, struct epoll_event *events,int maxevents, int timeout);等待事件的产生参数events用来从内核得到事件的集合maxevents告之内核这个events有多大这个 maxevents的值不能大于创建epoll_create()时的size参数timeout是超时时间毫秒0会立即返回-1将不确定也有说法说是永久阻塞。该函数返回需要处理的事件数目如返回0表示已超时。资料总结这么多其实都是一些理论关键还在于代码下面附上我使用epoll开发的服务端和客户端该代码我会上传到我的资源里可以免费下载。链接如果代码有bug,可以告诉我。程序demo首先对服务端和客户端做下说明我想实现的是客户端和服务端并发的程序客户端通过配置并发数说明有多少个用户去连接服务端。客户端会发送消息Client: i send message Hello Server!”其中i表示哪一个客户端收到消息Recv Server Msg Content:%s\n。例如发送Client: 1 send message Hello Server!接收Recv Derver Msg Content:Hello, client fd: 6服务端收到后给客户端回复消息Hello, client fd: i其中i表示服务端接收的fd,用户区别是哪一个客户端。接收客户端消息Terminal Received Msg Content:%s\n例如发送Hello, client fd: 6接收Terminal Received Msg Content:Client: 1 send message Hello Server!备注这里在接收到消息后直接打印出消息如果需要对消息进行处理如果消息处理比较占用时间不能立即返回可以将该消息放入一个队列中然后开启一个线程从队列中取消息进行处理这样的话不会因为消息处理而阻塞epoll。libenent好像对这种有2中处理方式一个就是回调要求回调函数不占用太多的时间基本能立即返回另一种好像也是一个队列实现的这个还需要研究。服务端代码说明服务端在绑定监听后开启了一个线程用于负责接收客户端连接加入到epoll中这样只要accept到客户端的连接就将其add EPOLLIN到epoll中然后进入循环调用epoll_wait监听到读事件接收数据并将事件修改为EPOLLOUT反之监听到写事件发送数据并将事件修改为EPOLLIN。 [cpp] view plain copycepollserver.h  #ifndef  C_EPOLL_SERVER_H  #define  C_EPOLL_SERVER_H    #include sys/epoll.h  #include sys/socket.h  #include netinet/in.h  #include fcntl.h  #include arpa/inet.h  #include stdio.h  #include stdlib.h  #include iostream  #include pthread.h    #define _MAX_SOCKFD_COUNT 65535    class CEpollServer  {          public:                  CEpollServer();                  ~CEpollServer();                    bool InitServer(const char* chIp, int iPort);                  void Listen();                  static void ListenThread( void* lpVoid );                  void Run();            private:                  int        m_iEpollFd;                  int        m_isock;                  pthread_t       m_ListenThreadId;// 监听线程句柄    };    #endif  cepollserver.cpp[cpp] view plain copy#include cepollserver.h    using namespace std;    CEpollServer::CEpollServer()  {  }    CEpollServer::~CEpollServer()  {      close(m_isock);  }    bool CEpollServer::InitServer(const char* pIp, int iPort)  {      m_iEpollFd  epoll_create(_MAX_SOCKFD_COUNT);        //设置非阻塞模式      int opts  O_NONBLOCK;      if(fcntl(m_iEpollFd,F_SETFL,opts)0)      {          printf(设置非阻塞模式失败!\n);          return false;      }        m_isock  socket(AF_INET,SOCK_STREAM,0);      if ( 0  m_isock )      {          printf(socket error!\n);          return false;    }        sockaddr_in listen_addr;        listen_addr.sin_familyAF_INET;        listen_addr.sin_porthtons ( iPort );        listen_addr.sin_addr.s_addrhtonl(INADDR_ANY);        listen_addr.sin_addr.s_addrinet_addr(pIp);            int ireuseadd_on  1;//支持端口复用        setsockopt(m_isock, SOL_SOCKET, SO_REUSEADDR, ireuseadd_on, sizeof(ireuseadd_on) );            if ( bind ( m_isock, ( sockaddr * ) listen_addr,sizeof ( listen_addr ) ) !0 )        {            printf(bind error\n);            return false;        }            if ( listen ( m_isock, 20) 0 )        {            printf(listen error!\n);            return false;        }        else        {            printf(服务端监听中...\n);        }            // 监听线程此线程负责接收客户端连接加入到epoll中        if ( pthread_create( m_ListenThreadId, 0, ( void * ( * ) ( void * ) ) ListenThread, this ) ! 0 )        {            printf(Server 监听线程创建失败!!!);            return false;        }    }    // 监听线程    void CEpollServer::ListenThread( void* lpVoid )    {        CEpollServer *pTerminalServer  (CEpollServer*)lpVoid;        sockaddr_in remote_addr;        int len  sizeof (remote_addr);        while ( true )        {            int client_socket  accept (pTerminalServer-m_isock, ( sockaddr * ) remote_addr,(socklen_t*)len );            if ( client_socket  0 )            {                printf(Server Accept失败!, client_socket: %d\n, client_socket);                continue;            }            else            {                struct epoll_event    ev;                ev.events  EPOLLIN | EPOLLERR | EPOLLHUP;                ev.data.fd  client_socket;     //记录socket句柄                epoll_ctl(pTerminalServer-m_iEpollFd, EPOLL_CTL_ADD, client_socket, ev);            }        }    }        void CEpollServer::Run()    {        while ( true )        {            struct epoll_event    events[_MAX_SOCKFD_COUNT];            int nfds  epoll_wait( m_iEpollFd, events,  _MAX_SOCKFD_COUNT, -1 );            for (int i  0; i  nfds; i)            {                int client_socket  events[i].data.fd;                char buffer[1024];//每次收发的字节数小于1024字节                memset(buffer, 0, 1024);                if (events[i].events  EPOLLIN)//监听到读事件接收数据                {                    int rev_size  recv(events[i].data.fd,buffer, 1024,0);                    if( rev_size  0 )                    {                        cout  recv error: recv size:   rev_size  endl;                        struct epoll_event event_del;                        event_del.data.fd  events[i].data.fd;                        event_del.events  0;                        epoll_ctl(m_iEpollFd, EPOLL_CTL_DEL, event_del.data.fd, event_del);                    }                    else                    {                        printf(Terminal Received Msg Content:%s\n,buffer);                        struct epoll_event    ev;                        ev.events  EPOLLOUT | EPOLLERR | EPOLLHUP;                        ev.data.fd  client_socket;     //记录socket句柄                        epoll_ctl(m_iEpollFd, EPOLL_CTL_MOD, client_socket, ev);                    }                }    else if(events[i].events  EPOLLOUT)//监听到写事件发送数据                {                    char sendbuff[1024];                    sprintf(sendbuff, Hello, client fd: %d\n, client_socket);                    int sendsize  send(client_socket, sendbuff, strlen(sendbuff)1, MSG_NOSIGNAL);                    if(sendsize  0)                    {                        struct epoll_event event_del;                        event_del.data.fd  events[i].data.fd;                        event_del.events  0;                        epoll_ctl(m_iEpollFd, EPOLL_CTL_DEL, event_del.data.fd, event_del);                    }                    else                    {                        printf(Server reply msg ok! buffer: %s\n, sendbuff);                        struct epoll_event    ev;                        ev.events  EPOLLIN | EPOLLERR | EPOLLHUP;                        ev.data.fd  client_socket;     //记录socket句柄                        epoll_ctl(m_iEpollFd, EPOLL_CTL_MOD, client_socket, ev);                    }                }                else                {                    cout  EPOLL ERROR\n endl;                    epoll_ctl(m_iEpollFd, EPOLL_CTL_DEL, events[i].data.fd, events[i]);                }            }        }    }  main.cpp[cpp] view plain copy#include iostream  #include cepollserver.h    using namespace std;    int main()  {          CEpollServer  theApp;          theApp.InitServer(127.0.0.1, 8000);          theApp.Run();            return 0;  }  客户端代码说明测试是两个并发进行测试每一个客户端都是一个长连接。代码中在连接服务器ConnectToServer时将用户ID和socketid关联起来。用户ID和socketid是一一对应的关系。cepollclient.h[cpp] view plain copy#ifndef _DEFINE_EPOLLCLIENT_H_  #define _DEFINE_EPOLLCLIENT_H_  #define _MAX_SOCKFD_COUNT 65535    #includeiostream  #include sys/epoll.h  #include sys/socket.h  #include netinet/in.h  #include fcntl.h  #include arpa/inet.h  #include errno.h  #include sys/ioctl.h  #include sys/time.h  #include string    using namespace std;    /**  * brief 用户状态  */  typedef enum _EPOLL_USER_STATUS_EM  {          FREE  0,          CONNECT_OK  1,//连接成功          SEND_OK  2,//发送成功          RECV_OK  3,//接收成功  }EPOLL_USER_STATUS_EM;    /*brief  *CEpollClient class 用户状态结构体  */  struct UserStatus  {          EPOLL_USER_STATUS_EM iUserStatus;//用户状态          int iSockFd;//用户状态关联的socketfd          char cSendbuff[1024];//发送的数据内容          int iBuffLen;//发送数据内容的长度          unsigned int uEpollEvents;//Epoll events  };    class CEpollClient  {          public:                    /**                  * brief                  * 函数名:CEpollClient                  * 描述:构造函数                  * param [in] iUserCount                   * param [in] pIP IP地址                  * param [in] iPort 端口号                  * return 无返回                  */                  CEpollClient(int iUserCount, const char* pIP, int iPort);    /**                  * brief                  * 函数名:CEpollClient                  * 描述:析构函数                  * return 无返回                  */                  ~CEpollClient();                    /**                  * brief                  * 函数名:RunFun                  * 描述:对外提供的接口运行epoll类                  * return 无返回值                  */                  int RunFun();            private:                    /**                  * brief                  * 函数名:ConnectToServer                  * 描述:连接到服务器                  * param [in] iUserId 用户ID                  * param [in] pServerIp 连接的服务器IP                  * param [in] uServerPort 连接的服务器端口号                  * return 成功返回socketfd,失败返回的socketfd为-1                  */                  int ConnectToServer(int iUserId,const char *pServerIp,unsigned short uServerPort);    /**                  * brief                  * 函数名:SendToServerData                  * 描述:给服务器发送用户(iUserId)的数据                  * param [in] iUserId 用户ID                  * return 成功返回发送数据长度                  */                  int SendToServerData(int iUserId);                    /**                  * brief                  * 函数名:RecvFromServer                  * 描述:接收用户回复消息                  * param [in] iUserId 用户ID                  * param [in] pRecvBuff 接收的数据内容                  * param [in] iBuffLen 接收的数据长度                  * return 成功返回接收的数据长度失败返回长度为-1                  */                  int RecvFromServer(int iUserid,char *pRecvBuff,int iBuffLen);                    /**                  * brief                  * 函数名:CloseUser                  * 描述:关闭用户                  * param [in] iUserId 用户ID                  * return 成功返回true                  */                  bool CloseUser(int iUserId);    /**                  * brief                  * 函数名:DelEpoll                  * 描述:删除epoll事件                  * param [in] iSockFd socket FD                  * return 成功返回true                  */                  bool DelEpoll(int iSockFd);          private:                    int    m_iUserCount;//用户数量                  struct UserStatus *m_pAllUserStatus;//用户状态数组                  int    m_iEpollFd;//需要创建epollfd                  int    m_iSockFd_UserId[_MAX_SOCKFD_COUNT];//将用户ID和socketid关联起来                  int    m_iPort;//端口号                  char   m_ip[100];//IP地址  };    #endif  cepollclient.cpp[cpp] view plain copy#include cepollclient.h    CEpollClient::CEpollClient(int iUserCount, const char* pIP, int iPort)  {      strcpy(m_ip, pIP);      m_iPort  iPort;      m_iUserCount  iUserCount;      m_iEpollFd  epoll_create(_MAX_SOCKFD_COUNT);      m_pAllUserStatus  (struct UserStatus*)malloc(iUserCount*sizeof(struct UserStatus));      for(int iuserid0; iuseridiUserCount ; iuserid)      {          m_pAllUserStatus[iuserid].iUserStatus  FREE;          sprintf(m_pAllUserStatus[iuserid].cSendbuff, Client: %d send message \Hello Server!\\r\n, iuserid);          m_pAllUserStatus[iuserid].iBuffLen  strlen(m_pAllUserStatus[iuserid].cSendbuff)  1;          m_pAllUserStatus[iuserid].iSockFd  -1;      }      memset(m_iSockFd_UserId, 0xFF, sizeof(m_iSockFd_UserId));  }    CEpollClient::~CEpollClient()  {      free(m_pAllUserStatus);  }  int CEpollClient::ConnectToServer(int iUserId,const char *pServerIp,unsigned short uServerPort)  {      if( (m_pAllUserStatus[iUserId].iSockFd  socket(AF_INET,SOCK_STREAM,0) )  0 )      {          cout [CEpollClient error]: init socket fail, reason is:strerror(errno),errno is:errnoendl;          m_pAllUserStatus[iUserId].iSockFd  -1;          return  m_pAllUserStatus[iUserId].iSockFd;      }        struct sockaddr_in addr;      bzero(addr, sizeof(addr));      addr.sin_family  AF_INET;      addr.sin_port  htons(uServerPort);      addr.sin_addr.s_addr  inet_addr(pServerIp);        int ireuseadd_on  1;//支持端口复用      setsockopt(m_pAllUserStatus[iUserId].iSockFd, SOL_SOCKET, SO_REUSEADDR, ireuseadd_on, sizeof(ireuseadd_on));        unsigned long ul  1;      ioctl(m_pAllUserStatus[iUserId].iSockFd, FIONBIO, ul); //设置为非阻塞模式        connect(m_pAllUserStatus[iUserId].iSockFd, (const sockaddr*)addr, sizeof(addr));      m_pAllUserStatus[iUserId].iUserStatus  CONNECT_OK;      m_pAllUserStatus[iUserId].iSockFd  m_pAllUserStatus[iUserId].iSockFd;        return m_pAllUserStatus[iUserId].iSockFd;  }  int CEpollClient::SendToServerData(int iUserId)  {      sleep(1);//此处控制发送频率避免狂打日志正常使用中需要去掉      int isendsize  -1;      if( CONNECT_OK  m_pAllUserStatus[iUserId].iUserStatus || RECV_OK  m_pAllUserStatus[iUserId].iUserStatus)      {          isendsize  send(m_pAllUserStatus[iUserId].iSockFd, m_pAllUserStatus[iUserId].cSendbuff, m_pAllUserStatus[iUserId  ].iBuffLen, MSG_NOSIGNAL);          if(isendsize  0)          {              cout [CEpollClient error]: SendToServerData, send fail, reason is:strerror(errno),errno is:errno  endl;          }          else          {              printf([CEpollClient info]: iUserId: %d Send Msg Content:%s\n, iUserId, m_pAllUserStatus[iUserId].cSendbuff  );              m_pAllUserStatus[iUserId].iUserStatus  SEND_OK;          }      }      return isendsize;  }  int CEpollClient::RecvFromServer(int iUserId,char *pRecvBuff,int iBuffLen)  {      int irecvsize  -1;      if(SEND_OK  m_pAllUserStatus[iUserId].iUserStatus)      {          irecvsize  recv(m_pAllUserStatus[iUserId].iSockFd, pRecvBuff, iBuffLen, 0);          if(0  irecvsize)          {              cout [CEpollClient error]: iUserId:   iUserId  RecvFromServer, recv fail, reason is:strerror(errn  o),errno is:errnoendl;          }          else if(0  irecvsize)          {              cout [warning:] iUserId:  iUserId  RecvFromServer, STB收到数据为0表示对方断开连接,irecvsize:ire  cvsize,iSockFd: m_pAllUserStatus[iUserId].iSockFd  endl;          }          else          {              printf(Recv Server Msg Content:%s\n, pRecvBuff);              m_pAllUserStatus[iUserId].iUserStatus  RECV_OK;          }      }      return irecvsize;  }    bool CEpollClient::CloseUser(int iUserId)  {      close(m_pAllUserStatus[iUserId].iSockFd);      m_pAllUserStatus[iUserId].iUserStatus  FREE;      m_pAllUserStatus[iUserId].iSockFd  -1;      return true;  }        int CEpollClient::RunFun()  {      int isocketfd  -1;      for(int iuserid0; iuseridm_iUserCount; iuserid)      {          struct epoll_event event;          isocketfd  ConnectToServer(iuserid, m_ip, m_iPort);          if(isocketfd  0)              cout [CEpollClient error]: RunFun, connect fail endl;          m_iSockFd_UserId[isocketfd]  iuserid;//将用户ID和socketid关联起来            event.data.fd  isocketfd;          event.events  EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP;            m_pAllUserStatus[iuserid].uEpollEvents  event.events;          epoll_ctl(m_iEpollFd, EPOLL_CTL_ADD, event.data.fd, event);    }    while(1)        {            struct epoll_event events[_MAX_SOCKFD_COUNT];            char buffer[1024];            memset(buffer,0,1024);            int nfds  epoll_wait(m_iEpollFd, events, _MAX_SOCKFD_COUNT, 100 );//等待epoll事件的产生            for (int ifd0; ifdnfds; ifd)//处理所发生的所有事件            {                struct epoll_event event_nfds;                int iclientsockfd  events[ifd].data.fd;                cout  events[ifd].data.fd:   events[ifd].data.fd  endl;                int iuserid  m_iSockFd_UserId[iclientsockfd];//根据socketfd得到用户ID                if( events[ifd].events  EPOLLOUT )                {                    int iret  SendToServerData(iuserid);                    if( 0  iret )                    {                        event_nfds.events  EPOLLIN|EPOLLERR|EPOLLHUP;                        event_nfds.data.fd  iclientsockfd;                        epoll_ctl(m_iEpollFd, EPOLL_CTL_MOD, event_nfds.data.fd, event_nfds);                    }                    else                    {                        cout [CEpollClient error:] EpollWait, SendToServerData fail, send iret:iret,iuserid:iuser    id,fd:events[ifd].data.fdendl;                        DelEpoll(events[ifd].data.fd);                        CloseUser(iuserid);                    }                }    else if( events[ifd].events  EPOLLIN )//监听到读事件接收数据                {                    int ilen  RecvFromServer(iuserid, buffer, 1024);                    if(0  ilen)                    {                        cout [CEpollClient error]: RunFun, recv fail, reason is:strerror(errno),errno is:errnoe    ndl;                        DelEpoll(events[ifd].data.fd);                        CloseUser(iuserid);                    }                    else if(0  ilen)                    {                        cout [CEpollClient warning:] server disconnect,ilen:ilen,iuserid:iuserid,fd:events[    ifd].data.fdendl;                        DelEpoll(events[ifd].data.fd);                        CloseUser(iuserid);                    }                    else                    {                        m_iSockFd_UserId[iclientsockfd]  iuserid;//将socketfd和用户ID关联起来                        event_nfds.data.fd  iclientsockfd;                        event_nfds.events  EPOLLOUT|EPOLLERR|EPOLLHUP;                        epoll_ctl(m_iEpollFd, EPOLL_CTL_MOD, event_nfds.data.fd, event_nfds);                    }                }                else                {                    cout [CEpollClient error:] other epoll errorendl;                    DelEpoll(events[ifd].data.fd);                    CloseUser(iuserid);                }            }    }    }        bool CEpollClient::DelEpoll(int iSockFd)    {        bool bret  false;        struct epoll_event event_del;        if(0  iSockFd)        {            event_del.data.fd  iSockFd;            event_del.events  0;            if( 0  epoll_ctl(m_iEpollFd, EPOLL_CTL_DEL, event_del.data.fd, event_del) )            {                bret  true;            }            else            {                cout [SimulateStb error:] DelEpoll,epoll_ctl error,iSockFd:iSockFdendl;            }            m_iSockFd_UserId[iSockFd]  -1;        }        else        {            bret  true;            }        return bret;    }  main.cpp[cpp] view plain copy#include cepollclient.h    int main(int argc, char *argv[])  {          CEpollClient *pCEpollClient  new CEpollClient(2, 127.0.0.1, 8000);          if(NULL  pCEpollClient)          {                  cout[epollclient error]:main initInit CEpollClient failendl;          }            pCEpollClient-RunFun();            if(NULL ! pCEpollClient)          {                  delete pCEpollClient;                  pCEpollClient  NULL;          }            return 0;  }  运行结果客户端服务端如是转载请指明原出处http://blog.csdn.net/feitianxuxue谢谢合作
http://www.zqtcl.cn/news/513175/

相关文章:

  • 网站安全怎么做手机网站 焦点图
  • 阿里云做网站的代码网上申请入团网站
  • 精品课程网站怎么做建筑图纸符号大全解释
  • 高权重网站 内页做跳转给新网站许昌做网站公司哪家专业
  • 咸阳网站建设工作室网站建设经
  • 网站怎么做短信接口新浪wordpress
  • 方维o2o 2.9蓝色团购网站程序源码模板做一电影网站怎么赚钱
  • 口碑好网站建设资源新昌网站建设
  • 苏州做网站的公司排名泉州网络推广专员
  • 无为县做互联网网站备案的时候网站建设方案书要吗
  • 修改网站的备案主体dede网站地图不显示文章列表
  • 建立个人网站的成本织梦html5手机网站模板
  • 怎么自己建一个网站吗php网页设计培训
  • 深圳大型论坛网站建设wordpress国内加速
  • 仿站怎么做广告装饰公司名字
  • 黄冈网站推广收费标准wordpress导航页面设置密码
  • 做网站会犯法吗贵州省建设厅城乡建设网站
  • 做网站和做公众号资金盘网站怎么建设
  • 全国最好的网站建设案例推广方法视频
  • 嘉兴网站建设策划方案在海口注册公司需要什么条件
  • 旅游网站国际业务怎样做建设企业官方网站企业登录
  • 北京市昌平网站建设小米网络营销案例分析
  • 怎么利用360域名做网站微信商城怎么弄
  • 中山h5网站建设天津网站建设技术托管
  • 建网站买的是什么商城网站建设合同
  • 购物网站制作样例有没有专门学做婴儿衣服的网站
  • 济南网站建设 找小七买友情链接有用吗
  • 南阳网站建设域名公司泉州关键词排名seo
  • 网站建设在线推广宁夏快速自助制作网站
  • 专业网站建设好不好wordpress编辑文章更新失败