说明:当客户端连接数超过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模型的更多相关文章

  1. IO模型,非阻塞IO模型,select实现多路复用

    1. IO阻塞模型 IO问题: 输入输出 我要一个用户名用来执行登陆操作,问题用户名需要用户输入,输入需要耗时, 如果输入没有完成,后续逻辑无法继续,所以默认的处理方式就是 等 将当前进程阻塞住,切换 ...

  2. 多路复用 阻塞/非阻塞IO模型 网络IO两个阶段

    1.网络IO的两个阶段 waitdata copydata send 先经历:copydata阶段 recv 先经历:waitdata阶段 再经历 copydata阶段 2.阻塞的IO模型 之前写的都 ...

  3. Python之阻塞IO模型与非阻塞IO模型

    Python之阻塞IO模型与非阻塞IO模型 IO模型 1 阻塞IO: 全程阻塞 2 非阻塞IO: 发送多次系统调用: 优点:wait for data时无阻塞 缺点:1 系统调用太多 2 数据不是实时 ...

  4. python 之 并发编程(非阻塞IO模型、I/O多路复用、socketserver的使用)

    9.16 非阻塞IO模型 cpu占用率过高 服务端: from socket import * import time s = socket() s.bind(('127.0.0.1',8080)) ...

  5. NIO【同步非阻塞io模型】关于 NIO socket 的详细总结【Java客户端+Java服务端 + 业务层】【可以客户端间发消息】

    1.前言 以前使用 websocket来实现双向通信,如今深入了解了 NIO 同步非阻塞io模型 , 优势是 处理效率很高,吞吐量巨大,能很快处理大文件,不仅可以 做 文件io操作, 还可以做sock ...

  6. 网络IO模型 非阻塞IO模型

    网络IO模型 非阻塞IO模型 同步 一件事做完后再做另一件事情 异步 同时做多件事情 相对论 多线程 多进程 协程 异步的程序 宏观角度:异步 并发聊天 阻塞IO 阻塞IO的问题 一旦阻塞就不能做其他 ...

  7. python 并发编程 非阻塞IO模型

    非阻塞IO(non-blocking IO) Linux下,可以通过设置socket使其变为non-blocking.当对一个non-blocking socket执行读操作时,流程是这个样子: 从图 ...

  8. 非阻塞IO模型

    #include<stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> # ...

  9. python 简单搭建非阻塞式单进程,select模式,epoll模式服务

    由于经常被抓取文章内容,在此附上博客文章网址:,偶尔会更新某些出错的数据或文字,建议到我博客地址 :  --> 点击这里 可以看我的上篇文章 <python 简单搭建阻塞式单进程,多进程, ...

随机推荐

  1. jquery.validate.js使用说明——后台添加用户邮箱功能:非空、不能重复、格式正确

    重点内容为:  jQuery验证控件jquery.validate.js使用说明+中文API[http://www.tuicool.com/articles/iABvI3] 简单教程可以参考[jQue ...

  2. Google地图接口API之地图类型(六)

    1. Google 地图- 基本地图类型 Google Maps API 中提供了以下地图类型: MapTypeId.ROADMAP,用于显示默认的道路地图视图 MapTypeId.SATELLITE ...

  3. Codeforces Round #328 (Div. 2)

    这场CF,准备充足,回寝室洗了澡,睡了一觉,可结果...   水 A - PawnChess 第一次忘记判断相等时A先走算A赢,hack掉.后来才知道自己的代码写错了(摔 for (int i=1; ...

  4. POJ 1651 (区间DP)

    题目链接: http://poj.org/problem?id=1651 题目大意:加分取牌.如果一张牌左右有牌则可以取出,分数为左牌*中牌*右牌.这样最后肯定还剩2张牌.求一个取牌顺序,使得加分最少 ...

  5. TYVJ P1072 bomb Label:看不懂题意

    描述 一场战争正在A国与B国之间如火如荼的展开.B国凭借其强大的经济实力开发出了无数的远程攻击导弹,B国的领导人希望,通过这些导弹直接毁灭A国的指挥部,从而取得战斗的胜利!当然,A国人民不会允许这样的 ...

  6. CC150 - 11.2

    Question: Write a method to sort an array of strings so that all the anagrams are next to each other ...

  7. COJ 删除数字

    试题描述 输入正整数N和M,在N中删除掉M位,能留下的最大整数是多少? 输入 正整数N和M 输出 留下的最大整数 输入示例 233390323 5 输出示例 9323 其他说明 1<=N< ...

  8. Google Code Jam 2010 Round 1C Problem B. Load Testing

    https://code.google.com/codejam/contest/619102/dashboard#s=p1&a=1 Problem Now that you have won ...

  9. MySQL索引分析与优化

    1.MySQL能够在name的索引中查找“Mike”值,然后直接转到数据文件中相应的行,准确地返回该行的 peopleid(999).在这个过程中,MySQL只需处理一个行就可以返回结果.如果没有“n ...

  10. 记save函数

    在写商品修改的代码的时候,我使用到了create()函数,也使用到了save函数.但是我从表单接受过来的数据,在添加语句的时候都没成功.代码如下 function upd($goods_id){ $g ...