C++ Windows 上简单的非阻塞Select模型
说明:当客户端连接数超过64个的时候,每次最多select64个,但每一帧可以select多次,理论上可以突破fd个数的限制
.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 + > maxfdp){ maxfdp = fd + ; }
- }
- void FDZero()
- {
- FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&errorfds);
- maxfdp = ;
- }
- 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 = ;
- 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, );
- 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 / ;
- timeout.tv_usec = nTimeUsec % ;
- static int32_t addrSize = sizeof(SOCKADDR_IN);
- static char buf[];
- static SOCKADDR_IN addrRemote;
- // select all used fd
- uint32_t unStartPos = , unEndPos = ;
- do
- {
- // reset fd_set
- FDZero();
- // fd_set size limited by 'FD_SETSIZE'
- for (uint32_t i = ; i < FD_SETSIZE && unEndPos < unFdSize; ++i)
- {
- FDSet(arrFd[unEndPos++]);
- }
- nRet = select(maxfdp, &readfds, &writefds, &errorfds, &timeout);
- // select error
- if (nRet == -)
- {
- int32_t nError = WSAGetLastError();
- perrors("select error,nRet=%d,info=%s\n", nError, strerror(nError));
- exit();
- }
- // time out ,nothing happened
- else if (nRet == )
- {
- printf(".");
- continue;
- }
- // some thing happened
- else if (nRet > )
- {
- // 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, , );
- if (nRet == || nRet == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)
- {
- // client close
- DelFd(i);
- }
- else
- {
- // received correct data from client
- buf[nRet] = '\0';
- send(arrFd[i], buf, strlen(buf), );
- }
- }
- }
- // write events
- else if (FD_ISSET(arrFd[i], &writefds))
- {
- Sleep();
- //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 -;
- }
- int32_t CModuleSelect::DelFd(uint32_t index)
- {
- if (unFdSize > && index > && unFdSize > index)
- {
- closesocket(arrFd[index]);
- arrFd[index] = arrFd[unFdSize - ];
- --unFdSize;
- }
- return S_OK;
- }
C++ Windows 上简单的非阻塞Select模型的更多相关文章
- IO模型,非阻塞IO模型,select实现多路复用
1. IO阻塞模型 IO问题: 输入输出 我要一个用户名用来执行登陆操作,问题用户名需要用户输入,输入需要耗时, 如果输入没有完成,后续逻辑无法继续,所以默认的处理方式就是 等 将当前进程阻塞住,切换 ...
- 多路复用 阻塞/非阻塞IO模型 网络IO两个阶段
1.网络IO的两个阶段 waitdata copydata send 先经历:copydata阶段 recv 先经历:waitdata阶段 再经历 copydata阶段 2.阻塞的IO模型 之前写的都 ...
- Python之阻塞IO模型与非阻塞IO模型
Python之阻塞IO模型与非阻塞IO模型 IO模型 1 阻塞IO: 全程阻塞 2 非阻塞IO: 发送多次系统调用: 优点:wait for data时无阻塞 缺点:1 系统调用太多 2 数据不是实时 ...
- python 之 并发编程(非阻塞IO模型、I/O多路复用、socketserver的使用)
9.16 非阻塞IO模型 cpu占用率过高 服务端: from socket import * import time s = socket() s.bind(('127.0.0.1',8080)) ...
- NIO【同步非阻塞io模型】关于 NIO socket 的详细总结【Java客户端+Java服务端 + 业务层】【可以客户端间发消息】
1.前言 以前使用 websocket来实现双向通信,如今深入了解了 NIO 同步非阻塞io模型 , 优势是 处理效率很高,吞吐量巨大,能很快处理大文件,不仅可以 做 文件io操作, 还可以做sock ...
- 网络IO模型 非阻塞IO模型
网络IO模型 非阻塞IO模型 同步 一件事做完后再做另一件事情 异步 同时做多件事情 相对论 多线程 多进程 协程 异步的程序 宏观角度:异步 并发聊天 阻塞IO 阻塞IO的问题 一旦阻塞就不能做其他 ...
- python 并发编程 非阻塞IO模型
非阻塞IO(non-blocking IO) Linux下,可以通过设置socket使其变为non-blocking.当对一个non-blocking socket执行读操作时,流程是这个样子: 从图 ...
- 非阻塞IO模型
#include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> # ...
- python 简单搭建非阻塞式单进程,select模式,epoll模式服务
由于经常被抓取文章内容,在此附上博客文章网址:,偶尔会更新某些出错的数据或文字,建议到我博客地址 : --> 点击这里 可以看我的上篇文章 <python 简单搭建阻塞式单进程,多进程, ...
随机推荐
- http://love3400wind.blog.163.com/blog/static/7963080120132794359703/
http://love3400wind.blog.163.com/blog/static/7963080120132794359703/
- Mesh系列文章 - 自定义Mesh
就是在做项目的过程中,有用到三角形的,今天就写一下如何自定义三角形? 先截个图,让大家有个感性认识! //引用 using UnityEngine; using System.Colle ...
- Beat the Spread![HDU1194]
Beat the Spread! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- topcoder 594 DIV2 foxandclassroom
暴力枚举 1 #include <iostream> #include <vector> #include <string> using namespace std ...
- 【TYVJ】1307 联络员(最小生成树)
http://tyvj.cn/Problem_Show.aspx?id=1307 kruskal裸题.(水题红色警报) #include <cstdio> #include <cst ...
- JS实现上下左右四方向无间隙滚动
想必大家都注意到<marquee>的不循环滚动,所以出现了很多替代脚本,或iframe或JS输出< marquee>,不管怎么做,都略显麻烦.下面说一下这个相对简单的实现思路: ...
- 模板引擎freemarker的简单使用教程
freemarker十分强大,而且不依赖web容器,个人感觉十分好用. 下面直接进主题,freemarker还有什么特性,请找度娘或谷哥~ 一.freemarker生成word 1.创建模板. 我创建 ...
- Spring整合Quartz实现持久化、动态设定时间
一.spring整合 网上一搜有很多整合的方式,这里我采用了其中的一种(暂时还没有对其他的方法研究过). 对于spring的整合其中的任务,spring提供了几个类.接口(这些类都实现了Job接口): ...
- ckeditor的详细配置
CKEditor 3 JavaScript API Documentation : http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.con ...
- Qt5.4 VS2010 Additional Dependancies
Go to Linker -> General -> Additional LIbrary Directories: qtmaind.libQt5Cored.libQt5Guid.libQ ...