C++ Windows 上简单的非阻塞Select模型
2016-07-31 13:00
295 查看
说明:当客户端连接数超过64个的时候,每次最多select64个,但每一帧可以select多次,理论上可以突破fd个数的限制
.h
.cpp
.h
#ifndef _MODULE_SELECT_H_ #define _MODULE_SELECT_H_ #include "platform/platform.h" class CModuleSelect { public: CModuleSelect(); ~CModuleSelect(); public: int32_t Initialize(); int32_t Uninitialize(); void ProcessEvent(uint32_t nTimeUsec); public: int32_t AddFd(int32_t fd); int32_t DelFd(uint32_t index); protected: void FDSet(int32_t fd) { FD_SET(fd, &readfds); FD_SET(fd, &writefds); FD_SET(fd, &errorfds); if (fd + 1 > maxfdp){ maxfdp = fd + 1; } } void FDZero() { FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&errorfds); maxfdp = 0; } void FDClear(int32_t fd) { FD_CLR(fd, &readfds); FD_CLR(fd, &writefds); FD_CLR(fd, &errorfds); }; private: int32_t sListen; // fd_set for select int32_t maxfdp; struct fd_set readfds, writefds, errorfds; // all used fd uint32_t unFdSize; int32_t *arrFd; }; #endif
.cpp
#include "module_select.h" #include "common/common.h" CModuleSelect::CModuleSelect() { unFdSize = 0; arrFd = new int32_t[unMaxFdSize]; } CModuleSelect::~CModuleSelect() { Uninitialize(); } int32_t CModuleSelect::Initialize() { WSADATA wsaData; int32_t nRet = WSAStartup(0x0202, &wsaData); if (nRet != S_OK){ return WSAGetLastError(); } sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); nRet = AddFd(sListen); if (nRet != S_OK){ return nRet; } SOCKADDR_IN addrLocal; addrLocal.sin_addr.S_un.S_addr = htonl(INADDR_ANY); addrLocal.sin_family = AF_INET; addrLocal.sin_port = htons(nPort); // bind nRet = bind(sListen, (struct sockaddr*)&addrLocal, sizeof(SOCKADDR_IN)); if (nRet != S_OK){ return WSAGetLastError(); } // listen nRet = listen(sListen, 5); if (nRet != S_OK){ return WSAGetLastError(); } printf("listen:%d\n", sListen); return S_OK; } void CModuleSelect::ProcessEvent(uint32_t nTimeUsec) { int32_t nRet = S_OK; static struct timeval timeout; timeout.tv_sec = nTimeUsec / 1000000; timeout.tv_usec = nTimeUsec % 1000000; static int32_t addrSize = sizeof(SOCKADDR_IN); static char buf[1024]; static SOCKADDR_IN addrRemote; // select all used fd uint32_t unStartPos = 0, unEndPos = 0; do { // reset fd_set FDZero(); // fd_set size limited by 'FD_SETSIZE' for (uint32_t i = 0; i < FD_SETSIZE && unEndPos < unFdSize; ++i) { FDSet(arrFd[unEndPos++]); } nRet = select(maxfdp, &readfds, &writefds, &errorfds, &timeout); // select error if (nRet == -1) { int32_t nError = WSAGetLastError(); perrors("select error,nRet=%d,info=%s\n", nError, strerror(nError)); exit(1); } // time out ,nothing happened else if (nRet == 0) { printf("."); continue; } // some thing happened else if (nRet > 0) { // check events for (uint32_t i = unStartPos; i < unEndPos; ++i) { // read events if ( FD_ISSET(arrFd[i],&readfds) ) { printf("[%d]:read = %d\n",i,arrFd[i]); if (sListen == arrFd[i]) { nRet = accept(sListen, (struct sockaddr*)&addrRemote, &addrSize); printf("Accepted client:%s:%d\n", inet_ntoa(addrRemote.sin_addr), ntohs(addrRemote.sin_port)); AddFd(nRet); } else { nRet = recv(arrFd[i], buf, 1024, 0); if (nRet == 0 || nRet == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET) { // client close DelFd(i); } else { // received correct data from client buf[nRet] = '\0'; send(arrFd[i], buf, strlen(buf), 0); } } } // write events else if (FD_ISSET(arrFd[i], &writefds)) { Sleep(1); //printf("write = %d\n", arrFd[i]); } // error events else if (FD_ISSET(arrFd[i], &errorfds)) { printf("error = %d\n", arrFd[i]); } } } // for next loop unStartPos = unEndPos; }while (unEndPos < unFdSize); } int32_t CModuleSelect::Uninitialize() { return WSACleanup(); } int32_t CModuleSelect::AddFd(int32_t fd) { if (unFdSize < unMaxFdSize) { arrFd[unFdSize++] = fd; return S_OK; } return -1; } int32_t CModuleSelect::DelFd(uint32_t index) { if (unFdSize > 1 && index > 0 && unFdSize > index) { closesocket(arrFd[index]); arrFd[index] = arrFd[unFdSize - 1]; --unFdSize; } return S_OK; }
相关文章推荐
- 非阻塞套接字及select模型
- 非阻塞套接字及select模型案例
- 最简单的WSAEventSelect模型(注意注释的地方)
- Select 模型的使用 简单聊天室的实现
- socket阻塞与非阻塞,同步与异步、I/O模型,select与poll、epoll比较
- IO模型的简单记录select、poll、epoll
- 非阻塞套接字及select模型
- [网络编程]_[Socket]_[Socket 阻塞模式(blocking)下的 I/O模型(model) 之 Select 模型(model)初探]
- 网络编程:select模型的简单实例
- 非阻塞通信之select模型
- 非阻塞socket下客户端connect + select简单demo
- 非阻塞套接字及select模型 select(0,&fread,NULL,NULL,&timeOut);
- linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO
- libevent for qt网络模块,直接替换qt的select模型,支持epoll,select,pool.使用非常简单,无需修改以前的代码结构
- I/O模型:从阻塞到非阻塞再到select
- 简单HTTP服务器(select模型)
- 同步异步阻塞非阻塞网络IO模型select/epoll
- 简单理解I/O模型中的阻塞非阻塞与同步异步
- linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO
- UNIX环境高级编程学习之第十六章网络IPC:套接字 - 非阻塞的Socket通信Select模型(多路复用), 实用Socket通信模板。