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 简单搭建阻塞式单进程,多进程, ...
随机推荐
- PDA应用在WMS仓储管理系统 实现无线扫描出入库作业
WMS系统是根据仓储物流管理的建设实施经验而推出的一款专业化仓储管理软件.与传统进销存软件相比优势在于,其不但包含了正常的出入库.盘点等库存管理基本功能,重点在于可以实现仓库作业过程的管理,通过条码及 ...
- Tr A(矩阵快速幂)
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission( ...
- DP(01背包) UESTC 1218 Pick The Sticks (15CCPC C)
题目传送门 题意:长度为L的金条,将n根金棍尽可能放上去,要求重心在L上,使得价值最大,最多有两条可以长度折半的放上去. 分析:首先长度可能为奇数,先*2.然后除了两条特殊的金棍就是01背包,所以dp ...
- 使用INFORMATION_SCHEMA.Columns查询数据表结构
使用情形1:写数据字典(Word文档)时, 需要获取表结构,以加快书写速度,当然,前提是没有文档导出工具. 使用情形2:生成实体时, 前提也是没有代码生成工具. 脚本 SELECT A.COLUMN_ ...
- 分拆素数和[HDU2098]
分拆素数和 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- BZOJ1075 : [SCOI2007]最优驾车drive
设$f[i][j][k]$为到达$(i,j)$,用时为$\frac{k}{5lcm}$小时的最低耗油量,然后DP即可. #include<cstdio> const int N=12,M= ...
- BZOJ3750 : [POI2015]Pieczęć
枚举第一个位置,然后暴力检验. #include<cstdio> #define N 1010 int T,n,m,a,b,x,y,i,j,k,q[N*N][2],cnt;char s[N ...
- Transactional topologies —— 事务拓扑
事务拓扑是怎么回事? Storm guarantees that every message will be played through the topology at least once. St ...
- WP7.1 应用程序发布到Marketplace
从8月22起Windows Phone marketplace可以提交7.1 sdk开发的应用了,尽管提交页面和方式与7.0是同一个,但是还是会出现一些问题.并且在提交之前也注意一些问题. 7.0 应 ...
- BZOJ4408: [Fj Winter Camp 2016]神秘数
Description 一个可重复数字集合S的神秘数定义为最小的不能被S的子集的和表示的正整数.例如S={1,1,1,4,13}, 1 = 1 2 = 1+1 3 = 1+1+1 4 = 4 5 = ...