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

正规网站建设咨询电话wordpress右侧广告

正规网站建设咨询电话,wordpress右侧广告,网站建设销售招聘,网站html下载器select初识 select是系统提供的一个多路转接接口。 select系统调用可以让我们的程序同时监视多个文件描述符的上的事件是否就绪。 select的核心工作就是等#xff0c;当监视的多个文件描述符中有一个或多个事件就绪时#xff0c;select才会成功返回并将对应文件描述符的就绪…select初识 select是系统提供的一个多路转接接口。 select系统调用可以让我们的程序同时监视多个文件描述符的上的事件是否就绪。 select的核心工作就是等当监视的多个文件描述符中有一个或多个事件就绪时select才会成功返回并将对应文件描述符的就绪事件告知调用者。   select基本工作流程 如果我们要实现一个简单的select服务器该服务器要做的就是读取客户端发来的数据并进行打印那么这个select服务器的工作流程应该是这样的 先初始化服务器完成套接字的创建、绑定和监听。 定义一个fd_array数组用于保存监听套接字和已经与客户端建立连接的套接字刚开始时就将监听套接字添加到fd_array数组当中。 然后服务器开始循环调用select函数检测读事件是否就绪如果就绪则执行对应的操作。 每次调用select函数之前都需要定义一个读文件描述符集readfds并将fd_array当中的文件描述符依次设置进readfds当中表示让select帮我们监视这些文件描述符的读事件是否就绪。 当select检测到数据就绪时会将读事件就绪的文件描述符设置进readfds当中此时我们就能够得知哪些文件描述符的读事件就绪了并对这些文件描述符进行对应的操作。 如果读事件就绪的是监听套接字则调用accept函数从底层全连接队列获取已经建立好的连接并将该连接对应的套接字添加到fd_array数组当中。 如果读事件就绪的是与客户端建立连接的套接字则调用read函数读取客户端发来的数据并进行打印输出。 当然服务器与客户端建立连接的套接字读事件就绪也可能是因为客户端将连接关闭了此时服务器应该调用close关闭该套接字并将该套接字从fd_array数组当中清除因为下一次不需要再监视该文件描述符的读事件了。   log.hpp #pragma once#include iostream #include cstdio #include cstdarg #include ctime #include string// 日志是有日志级别的 #define DEBUG 0 #define NORMAL 1 #define WARNING 2 #define ERROR 3 #define FATAL 4const char *gLevelMap[] {DEBUG,NORMAL,WARNING,ERROR,FATAL };#define LOGFILE ./selectServer.log// 完整的日志功能至少: 日志等级 时间 支持用户自定义(日志内容, 文件行文件名) void logMessage(int level, const char *format, ...) {// va_list ap;// va_start(ap, format);// while()// int x va_arg(ap, int);// va_end(ap); //apnullptrchar stdBuffer[1024]; //标准部分time_t timestamp time(nullptr);// struct tm *localtime localtime(timestamp);snprintf(stdBuffer, sizeof stdBuffer, [%s] [%ld] , gLevelMap[level], timestamp);char logBuffer[1024]; //自定义部分va_list args;va_start(args, format);// vprintf(format, args);vsnprintf(logBuffer, sizeof logBuffer, format, args);va_end(args);// FILE *fp fopen(LOGFILE, a);printf(%s%s\n, stdBuffer, logBuffer);// fprintf(fp, %s%s\n, stdBuffer, logBuffer);// fclose(fp); } selectserver.hpp #include iostream #include cstring #include sys/select.h #include log.hpp #include sock.hpp #include string #include vector #include sys/types.h #include sys/time.h #include algorithm #define NUM 1024 #define FD_NONE -1 using namespace std; class SelectServer { public://端口类型设置为16位是因为TCP报文中端口号为16位SelectServer(const uint16_t port 8080):_port(port){_listensock Sock::Socket();Sock::Bind(_listensock,_port);Sock::Listen(_listensock);logMessage(DEBUG,%s,create base socket success);for(int i 0;i NUM;i) _fd_array[i] FD_NONE;_fd_array[0] _listensock;//规定第一个为监听套接字std::cout初始化完成....std::endl;} void start(){while(1){struct timeval timeout {0,0};fd_set rfds;FD_ZERO(rfds);int maxfd _listensock;for(int i 0;i NUM;i){if(_fd_array[i] FD_NONE) continue;FD_SET(_fd_array[i],rfds);maxfd max(maxfd,_fd_array[i]);}int n select(maxfd 1,rfds,nullptr, nullptr,timeout);DebugPrint();switch (n){case 0:sleep(1);logMessage(DEBUG,%s,time out...);break;case -1:logMessage(DEBUG,%s,select error);break;default://成功logMessage(DEBUG,%s,get a new link event........);//成功了的话如果不去读取的话会一直提醒读取也就是说链接好的//链接会被放在就绪队列中也就是看到链接在排队操作系统会一直提醒有连接成功//当你要取的时候会取队列的头部连接去执行//因为我们的select是检查_listensock有没有获取的连接已经到达Tcp层//如果到达的话就说明可以读走这个链接了所以我们检查的是IO//也就是读到连接的操作而不是建立连接的操作HandlerEvent(rfds);sleep(1);break;}}}private:uint16_t _port;int _listensock;int _fd_array[NUM];void HandlerEvent(const fd_set rfds){for(int i 0;i NUM;i){//1.去掉不合法的fd,也就是去掉没有建立连接的fd,也就是去掉数组里为FD_NONEif(_fd_array[i] FD_NONE) continue;//2.合法的就一定就绪了?,不一定所以需要FD_ISSET判断是否已经就绪if(FD_ISSET(_fd_array[i],rfds)){//1.如果是监听套接字就绪了那就是accept//2.如果不是的话,那就处理该链接进行读取函数if(_fd_array[i] _listensock) Accepter();else Recver(i);}}}void Accepter(){string clientip;uint16_t clientport;int sock Sock::Accept(_listensock,clientip,clientport);if(sock 0){logMessage(WARNING,%s %s:%d,accept error,strerror(errno),errno);return;}logMessage(DEBUG,get a new link success);int pos 0;for(;pos NUM;pos){if(_fd_array[pos] FD_NONE) break;}if(pos NUM){logMessage(WARNING, %s:%d, select server already fullclose: %d, sock);close(sock);}else{_fd_array[pos] sock;}}void Recver(int pos){logMessage(DEBUG,message in,get IO event:%d,_fd_array[pos]);// 暂时先不做封装, 此时select已经帮我们进行了事件检测fd上的数据一定是就绪的即 本次 不会被阻塞// 这样读取有bug吗有的你怎么保证以读到了一个完整包文呢char buffer[1024];int n recv(_fd_array[pos],buffer,sizeof(buffer) - 1,0);//不会堵塞if(n 0){buffer[n] 0;logMessage(DEBUG,client[%d]# %s,_fd_array[pos],buffer);}else if(n 0){logMessage(DEBUG, client[%d] quit, me too..., _fd_array[pos]);//对端关闭那么我也关闭close(_fd_array[pos]);_fd_array[pos] FD_NONE;}else{logMessage(WARNING, %d sock recv error, %d : %s, _fd_array[pos], errno, strerror(errno));close(_fd_array[pos]);_fd_array[pos] FD_NONE;}}void DebugPrint(){cout _fd_array[]: ;for(int i 0; i NUM; i){if(_fd_array[i] FD_NONE) continue;cout _fd_array[i] ;}cout endl;} }; sock.hpp #pragma once#include iostream #include string #include cstring #include cerrno #include cassert #include unistd.h #include memory #include sys/types.h #include sys/socket.h #include arpa/inet.h #include netinet/in.h #include ctype.h//全加静态成员让他变成一个方法 class Sock { private:// listen的第二个参数意义底层全连接队列的长度 listen的第二个参数1const static int gbacklog 10; public:Sock() {}static int Socket(){int listensock socket(AF_INET, SOCK_STREAM, 0);if (listensock 0){exit(2);}int opt 1;setsockopt(listensock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, opt, sizeof(opt));return listensock;}static void Bind(int sock, uint16_t port, std::string ip 0.0.0.0){struct sockaddr_in local;memset(local, 0, sizeof local);local.sin_family AF_INET;local.sin_port htons(port);inet_pton(AF_INET, ip.c_str(), local.sin_addr);if (bind(sock, (struct sockaddr *)local, sizeof(local)) 0){exit(3);}}static void Listen(int sock){if (listen(sock, gbacklog) 0){exit(4);}}// 一般经验// const std::string : 输入型参数// std::string *: 输出型参数// std::string : 输入输出型参数static int Accept(int listensock, std::string *ip, uint16_t *port){struct sockaddr_in src;socklen_t len sizeof(src);int servicesock accept(listensock, (struct sockaddr *)src, len);if (servicesock 0){return -1;}if(port) *port ntohs(src.sin_port);if(ip) *ip inet_ntoa(src.sin_addr);return servicesock;}static bool Connect(int sock, const std::string server_ip, const uint16_t server_port){struct sockaddr_in server;memset(server, 0, sizeof(server));server.sin_family AF_INET;server.sin_port htons(server_port);server.sin_addr.s_addr inet_addr(server_ip.c_str());if(connect(sock, (struct sockaddr*)server, sizeof(server)) 0) return true;else return false;}~Sock() {} }; main.cc #include selectserver.hpp using namespace std; int main() {SelectServer select;coutrunring.......endl;select.start(); } I/O多路转接之poll poll初识 poll也是系统提供的一个多路转接接口。 poll系统调用也可以让我们的程序同时监视多个文件描述符上的事件是否就绪和select的定位是一样的适用场景也是一样的。 poll的工作流程和select是基本类似的这里我们也实现一个简单poll服务器该服务器也只是读取客户端发来的数据并进行打印。 log.hpp #pragma once#include iostream #include cstdio #include cstdarg #include ctime #include string// 日志是有日志级别的 #define DEBUG 0 #define NORMAL 1 #define WARNING 2 #define ERROR 3 #define FATAL 4const char *gLevelMap[] {DEBUG,NORMAL,WARNING,ERROR,FATAL };#define LOGFILE ./selectServer.log// 完整的日志功能至少: 日志等级 时间 支持用户自定义(日志内容, 文件行文件名) void logMessage(int level, const char *format, ...) {// va_list ap;// va_start(ap, format);// while()// int x va_arg(ap, int);// va_end(ap); //apnullptrchar stdBuffer[1024]; //标准部分time_t timestamp time(nullptr);// struct tm *localtime localtime(timestamp);snprintf(stdBuffer, sizeof stdBuffer, [%s] [%ld] , gLevelMap[level], timestamp);char logBuffer[1024]; //自定义部分va_list args;va_start(args, format);// vprintf(format, args);vsnprintf(logBuffer, sizeof logBuffer, format, args);va_end(args);// FILE *fp fopen(LOGFILE, a);printf(%s%s\n, stdBuffer, logBuffer);// fprintf(fp, %s%s\n, stdBuffer, logBuffer);// fclose(fp); } pollserver.hpp #include iostream #include cstring #include sys/select.h #include log.hpp #include sock.hpp #include string #include vector #include sys/types.h #include sys/time.h #include algorithm #include poll.h #define NUM 1024 #define FD_NONE -1 using namespace std; class PollServer { public:static const int nfds 100; public:// struct pollfd {// int fd; // 文件描述符// short events; // 需要关注的事件// short revents; // 实际发生的事件// }; // fd待轮询的文件描述符。 // events关注的事件可以是以下值的组合 // POLLIN可读事件数据可读取 // POLLOUT可写事件数据可写入 // POLLERR错误事件发生错误 // POLLHUP挂起事件连接断开 // POLLNVAL无效事件文件描述符未打开 // revents实际发生的事件在调用 poll 后由系统设置。 // poll 函数将在等待期间阻塞并返回发生事件的数量如果超时则返回 0如果出错则返回 -1。// 您可以使用 poll 函数来同时监视多个文件描述符并根据发生的事件采取相应的操作。//端口类型设置为16位是因为TCP报文中端口号为16位PollServer(const uint16_t port 8080):_port(port),_nfds(nfds){_listensock Sock::Socket();Sock::Bind(_listensock,_port);Sock::Listen(_listensock);logMessage(DEBUG,%s,create base socket success);_fds new struct pollfd[_nfds];for(int i 0;i NUM;i) {_fds[i].fd FD_NONE;_fds[i].events _fds[i].revents 0;} _fds[0].fd _listensock;//规定第一个为监听套接字需要关注的套接字是什么这是对象方面_fds[0].events POLLIN;//需要套接字中关注的事件是读事件这个才是关系的动作_timeout 1000;std::cout初始化完成....std::endl;} void start(){while(1){int n poll(_fds,_nfds,_timeout);DebugPrint();switch (n){case 0:sleep(1);logMessage(DEBUG,%s,time out...);break;case -1:logMessage(DEBUG,%s,select error);break;default://成功logMessage(DEBUG,%s,get a new link event........);//成功了的话如果不去读取的话会一直提醒读取也就是说链接好的//链接会被放在就绪队列中也就是看到链接在排队操作系统会一直提醒有连接成功//当你要取的时候会取队列的头部连接去执行//因为我们的select是检查_listensock有没有获取的连接已经到达Tcp层//如果到达的话就说明可以读走这个链接了所以我们检查的是IO//也就是读到连接的操作而不是建立连接的操作HandlerEvent();sleep(1);break;}}}~PollServer(){if(_listensock 0) close(_listensock);if(!_fds) delete [] _fds;} private:uint16_t _port;int _listensock;int _timeout;struct pollfd* _fds;int _nfds;void HandlerEvent(){for(int i 0;i _nfds;i){//1.去掉不合法的fd,也就是去掉没有建立连接的fd,也就是去掉数组里为FD_NONEif(_fds[i].fd FD_NONE) continue;//2.合法的就一定就绪了?,不一定所以需要FD_ISSET判断是否已经就绪if(_fds[i].revents POLLIN)//判断读事件是否就绪就是就是一个数字{//1.如果是监听套接字就绪了那就是accept//2.如果不是的话,那就处理该链接进行读取函数if(_fds[i].fd _listensock) Accepter();else Recver(i);}}}void Accepter(){string clientip;uint16_t clientport;int sock Sock::Accept(_listensock,clientip,clientport);if(sock 0){logMessage(WARNING,%s %s:%d,accept error,strerror(errno),errno);return;}logMessage(DEBUG,get a new link success);int pos 0;for(;pos NUM;pos){if(_fds[pos].fd FD_NONE) break;}if(pos NUM){logMessage(WARNING, %s:%d, select server already fullclose: %d, sock);close(sock);}else{_fds[pos].fd sock;_fds[pos].events POLLIN;}}void Recver(int pos){logMessage(DEBUG,message in,get IO event:%d,_fds[pos].fd);// 暂时先不做封装, 此时select已经帮我们进行了事件检测fd上的数据一定是就绪的即 本次 不会被阻塞// 这样读取有bug吗有的你怎么保证以读到了一个完整包文呢char buffer[1024];int n recv(_fds[pos].fd,buffer,sizeof(buffer) - 1,0);//不会堵塞if(n 0){buffer[n] 0;logMessage(DEBUG,client[%d]# %s,_fds[pos].fd,buffer);}else if(n 0){logMessage(DEBUG, client[%d] quit, me too..., _fds[pos].fd);//对端关闭那么我也关闭close(_fds[pos].fd);_fds[pos].fd FD_NONE;_fds[pos].events 0;}else{logMessage(WARNING, %d sock recv error, %d : %s, _fds[pos].fd, errno, strerror(errno));close(_fds[pos].fd);_fds[pos].fd FD_NONE;_fds[pos].fd 0;}}void DebugPrint(){cout _fd_array[]: ;for(int i 0; i NUM; i){if(_fds[i].fd FD_NONE) continue;cout _fds[i].fd ;}cout endl;} }; sock.hpp #pragma once#include iostream #include string #include cstring #include cerrno #include cassert #include unistd.h #include memory #include sys/types.h #include sys/socket.h #include arpa/inet.h #include netinet/in.h #include ctype.hclass Sock { private:// listen的第二个参数意义底层全连接队列的长度 listen的第二个参数1const static int gbacklog 10; public:Sock() {}static int Socket(){int listensock socket(AF_INET, SOCK_STREAM, 0);if (listensock 0){exit(2);}int opt 1;setsockopt(listensock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, opt, sizeof(opt));return listensock;}static void Bind(int sock, uint16_t port, std::string ip 0.0.0.0){struct sockaddr_in local;memset(local, 0, sizeof local);local.sin_family AF_INET;local.sin_port htons(port);inet_pton(AF_INET, ip.c_str(), local.sin_addr);if (bind(sock, (struct sockaddr *)local, sizeof(local)) 0){exit(3);}}static void Listen(int sock){if (listen(sock, gbacklog) 0){exit(4);}}// 一般经验// const std::string : 输入型参数// std::string *: 输出型参数// std::string : 输入输出型参数static int Accept(int listensock, std::string *ip, uint16_t *port){struct sockaddr_in src;socklen_t len sizeof(src);int servicesock accept(listensock, (struct sockaddr *)src, len);if (servicesock 0){return -1;}if(port) *port ntohs(src.sin_port);if(ip) *ip inet_ntoa(src.sin_addr);return servicesock;}static bool Connect(int sock, const std::string server_ip, const uint16_t server_port){struct sockaddr_in server;memset(server, 0, sizeof(server));server.sin_family AF_INET;server.sin_port htons(server_port);server.sin_addr.s_addr inet_addr(server_ip.c_str());if(connect(sock, (struct sockaddr*)server, sizeof(server)) 0) return true;else return false;}~Sock() {} };main.cc #include pollserver.hpp using namespace std; int main() {PollServer pollserver;coutrunring.......endl;pollserver.start(); } /O多路转接之epoll epoll初识 epoll也是系统提供的一个多路转接接口。 epoll系统调用也可以让我们的程序同时监视多个文件描述符上的事件是否就绪与select和poll的定位是一样的适用场景也相同。 epoll在命名上比poll多了一个e这个e可以理解成是extendepoll就是为了同时处理大量文件描述符而改进的poll。 epoll在2.5.44内核中被引进它几乎具备了select和poll的所有优点被公认为Linux2.6下性能最好的多路I/O就绪通知方法。 epoll的相关系统调用 epoll有三个相关的系统调用分别是epoll_create、epoll_ctl和epoll_wait。 epoll工作原理 epoll.hpp #pragma once #include iostream #include sys/epoll.h #include unistd.h using namespace std; class Epoll { public:static const int gsize 256; public:static int CreateEpoll(){int epfd epoll_create(gsize);if(epfd 0) return epfd;exit(5);}static bool CtrlEpoll(int epfd,int oper,int sock,uint32_t events){struct epoll_event ev;ev.events events;ev.data.fd sock;int n epoll_ctl(epfd,oper,sock,ev);return n 0;}static int WaitEpoll(int epfd,struct epoll_event* revs,int num,int timeout){// 细节1如果底层就绪的sock非常多revs承装不下怎么办不影响一次拿不完就下一次再拿// 细节2关于epoll_wait的返回值问题有几个fd上的事件就绪就返回几epoll返回的时候会将所有// 就绪的event按照顺序放入到revs数组中一共有返回值个return epoll_wait(epfd,revs,num,timeout);} }; log.hpp #pragma once#include iostream #include cstdio #include cstdarg #include ctime #include string// 日志是有日志级别的 #define DEBUG 0 #define NORMAL 1 #define WARNING 2 #define ERROR 3 #define FATAL 4const char *gLevelMap[] {DEBUG,NORMAL,WARNING,ERROR,FATAL };#define LOGFILE ./selectServer.log// 完整的日志功能至少: 日志等级 时间 支持用户自定义(日志内容, 文件行文件名) void logMessage(int level, const char *format, ...) {// va_list ap;// va_start(ap, format);// while()// int x va_arg(ap, int);// va_end(ap); //apnullptrchar stdBuffer[1024]; //标准部分time_t timestamp time(nullptr);// struct tm *localtime localtime(timestamp);snprintf(stdBuffer, sizeof stdBuffer, [%s] [%ld] , gLevelMap[level], timestamp);char logBuffer[1024]; //自定义部分va_list args;va_start(args, format);// vprintf(format, args);vsnprintf(logBuffer, sizeof logBuffer, format, args);va_end(args);// FILE *fp fopen(LOGFILE, a);printf(%s%s\n, stdBuffer, logBuffer);// fprintf(fp, %s%s\n, stdBuffer, logBuffer);// fclose(fp); } sock.hpp #pragma once#include iostream #include string #include cstring #include cerrno #include cassert #include unistd.h #include memory #include sys/types.h #include sys/socket.h #include arpa/inet.h #include netinet/in.h #include ctype.h//全加静态成员让他变成一个方法 class Sock { private:// listen的第二个参数意义底层全连接队列的长度 listen的第二个参数1const static int gbacklog 10; public:Sock() {}static int Socket(){int listensock socket(AF_INET, SOCK_STREAM, 0);if (listensock 0){exit(2);}int opt 1;setsockopt(listensock, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, opt, sizeof(opt));return listensock;}static void Bind(int sock, uint16_t port, std::string ip 0.0.0.0){struct sockaddr_in local;memset(local, 0, sizeof local);local.sin_family AF_INET;local.sin_port htons(port);inet_pton(AF_INET, ip.c_str(), local.sin_addr);if (bind(sock, (struct sockaddr *)local, sizeof(local)) 0){exit(3);}}static void Listen(int sock){if (listen(sock, gbacklog) 0){exit(4);}}// 一般经验// const std::string : 输入型参数// std::string *: 输出型参数// std::string : 输入输出型参数static int Accept(int listensock, std::string *ip, uint16_t *port){struct sockaddr_in src;socklen_t len sizeof(src);int servicesock accept(listensock, (struct sockaddr *)src, len);if (servicesock 0){return -1;}if(port) *port ntohs(src.sin_port);if(ip) *ip inet_ntoa(src.sin_addr);return servicesock;}static bool Connect(int sock, const std::string server_ip, const uint16_t server_port){struct sockaddr_in server;memset(server, 0, sizeof(server));server.sin_family AF_INET;server.sin_port htons(server_port);server.sin_addr.s_addr inet_addr(server_ip.c_str());if(connect(sock, (struct sockaddr*)server, sizeof(server)) 0) return true;else return false;}~Sock() {} }; epollserver.hpp #include sock.hpp #include log.hpp #include memory #include sys/types.h #include cstring #include functional #include string #include epoll.hpp using namespace std; const static int default_port 8080; const static int gnum 64; using func_t functionvoid(string); class EpollServer { public:EpollServer(func_t HandlerRequese,const int port default_port):_port(port),_HandlerRequest(HandlerRequese),_revs_num(gnum){// 0. 申请对应的空间_revs new struct epoll_event[_revs_num];// 1. 创建listensock_listensock Sock::Socket();Sock::Bind(_listensock,_port);Sock::Listen(_listensock);//2.创建epoll模型_epfd Epoll::CreateEpoll();logMessage(DEBUG,init success,listensock: %d,epfd: %d,_listensock,_epfd);//3.将listensock加入到epoll模型中以关系读的事务加入if(!Epoll::CtrlEpoll(_epfd,EPOLL_CTL_ADD,_listensock,EPOLLIN)) exit(6);////EPOLLIN是读事务logMessage(DEBUG, add listensock to epoll success.); // 3, 4}void Accepter(int listensock){string clientip;uint16_t clientport;int sock Sock::Accept(listensock,clientip,clientport);if(sock 0) {logMessage(WARNING, accept error!);return;}// 能不能直接读取不能因为你并不清楚底层是否有数据// 将新的sock添加给epollif(!Epoll::CtrlEpoll(_epfd,EPOLL_CTL_ADD,sock,EPOLLIN)) exit(6);logMessage(DEBUG, add new sock : %d to epoll success, sock); }void Recver(int sock){char buffer[10240];ssize_t n recv(sock,buffer,sizeof(buffer) - 1,0);if(n 0){//假设这里就是读到了一个完整的报文 // 如何保证buffer[n] 0;_HandlerRequest(buffer); // 2. 处理数据}else if(n 0){// 1. 先在epoll中去掉对sock的关bool res Epoll::CtrlEpoll(_epfd,EPOLL_CTL_DEL,sock,0);assert(res);(void)res;//2.在close文件close(sock);logMessage(NORMAL,client %d quit,me too...,sock);}else{//1.先在epoll中去掉对sock的关心bool res Epoll::CtrlEpoll(_epfd,EPOLL_CTL_DEL,sock,0);assert(res);(void)res;close(sock);logMessage(NORMAL, client recv %d error, close error sock, sock);}}void HandlerEvents(int n){assert(n 0);for(int i 0;i n;i){uint32_t revents _revs[i].events;int sock _revs[i].data.fd;//看看是哪个fd就绪了if(revents EPOLLIN){if(sock _listensock) Accepter(_listensock);else Recver(sock);}if(revents EPOLLOUT){//TODO}}}void looponce(int timeout){int n Epoll::WaitEpoll(_epfd,_revs,_revs_num,timeout);//if(n _revs_num) //扩容switch (n)//返回值n,代表有一个关心的事务就绪{case 0:logMessage(DEBUG, timeout...); // 3, 4break;case -1:logMessage(WARNING, epoll wait error: %s, strerror(errno));break;default://等待成功有至少一个关系的事务已经就绪//去执行logMessage(DEBUG, get a event);HandlerEvents(n);break;}}void start(){int timeout 1000;while(1){looponce(timeout);}}~EpollServer(){if (_listensock 0)close(_listensock);if (_epfd 0)close(_epfd);if (_revs)delete[] _revs;} private:int _listensock;uint16_t _port;int _epfd;struct epoll_event* _revs;int _revs_num;func_t _HandlerRequest; };main.cc #include epollserver.hpp #include memory #include iostream #include string using namespace std; void change(string str) {coutstrendl; } int main() {EpollServer epollserver(change);coutrunring.......endl;epollserver.start(); }
http://www.dnsts.com.cn/news/148983.html

相关文章:

  • 做移门配件的网站安徽专业网站建设
  • 商务网站设计与制作wordpress tipton
  • 做网站和微信公众号需要多少钱宁波营销网站建设
  • php企业网站demo如何写wordpress插件
  • 药品在哪些网站做推广免费手游推广代理平台渠道
  • 最大的设计公司湖南关键词优化推荐
  • 河北省建设工程招标投标协会网站网页设计与制作教程第三版答案
  • 网站 在线支付功能用asp做的一个网站实例源代码
  • 网页设计制作音乐网站潮阳网站建设公司
  • 网站建设佰首选金手指二六wordpress 360急速模式打不开
  • 广西城市建设学校官方网站手机网站模板网
  • 云南网站建设价格php和网站建设
  • 襄阳网站seo技巧一个小程序一年的费用是多少
  • 网站页面html静态化是什么意思建设网站涉及的技术
  • wordpress後台建站登封seo公司
  • 站长统计导航窗口商城网站系统建设
  • 杭州有做网站深圳公众号小程序开发公司
  • 专业网站建设微信商城开发专业建设费用怎么花
  • 乌兰浩特网站建设wordpress抓取文章插件
  • 做网页用的网站wordpress 内页模板
  • 技术支持 网站建设国产做爰全免费的视频网站
  • 淘宝网站开发多少金额高级网站开发工程师 证书
  • php网站开发外包建设银行人力资源系统网站怎么进
  • 网站404页面设置郑州建设信息网打不开
  • 红色网站 推荐重庆娱乐场所最新通知
  • 网站开发菜鸟适合用什么软件郑州网站模板哪里有
  • 医院网站前置审批最快多久出来广州设计网站培训学校
  • 苍溪规划和建设局网站微信网站开发制作公司
  • 网站设计公司 长沙怎么做国外游戏下载网站
  • 做aa视频网站人社局网站建设步骤