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 简单搭建阻塞式单进程,多进程, ...
随机推荐
- Playmaker Input篇教程之Playmaker购买下载和导入
Playmaker Input篇教程之Playmaker购买下载和导入 Playmaker Input篇认识Playmaker Playmaker是Unity的插件,其标志如图1-1所示.开发者使用它 ...
- 万网云解析设置二级域名解析到同IP不同端口
http://jingyan.baidu.com/article/eb9f7b6d8a02a5869364e827.html
- CodeForces Round 195 Div2
A. Vasily the Bear and Triangletime limit per test1 secondmemory limit per test256 megabytesinputsta ...
- BZOJ3673 : 可持久化并查集
题目没有强制在线! 考虑离线做法. 把操作建立成一棵树的结构,然后按照欧拉序遍历,每次转移要么是一次合并操作,要么是一次撤销合并操作,可以看成是分离操作. 用LCT维护集合,合并就是加边,分离就是删边 ...
- AppCache 离线存储 应用程序缓存 API 及注意事项
使用ApplicationCache接口实现离线缓存 原文:http://www.mb5u.com/HTML5/html5_96464.html 推荐:html5 application cache遇 ...
- CentOS6.4 利用sendEmail发邮件
1.下载安装sendEmail wget http://caspian.dotconf.net/menu/Software/SendEmail/sendEmail-v1.56.tar.gz tar z ...
- TYVJ P1008 传球游戏
时间: 1000ms / 空间: 131072KiB / Java类名: Main 背景 NOIP2008复赛普及组第三题 描述 上体育课的时候,小蛮的老师经常带着同学们一起做游戏.这次,老师带着 ...
- RowDataBound事件
RowDataBound事件在创建gridView控件时,必须先为GridView的每一行创建一个GridViewRow对象,创建每一行时,将引发一个RowCreated事件:当行创建完毕,每一行Gr ...
- Spring Aop实例
一.XML方式 1. TestAspect:切面类 package com.spring.aop; import org.aspectj.lang.JoinPoint; import org.aspe ...
- 数据库SQL及相关
//1.生成随机数 ROUND(((89 - 71 -1) * RAND() + 71), 0) DECLARE @Result INT DECLARE @Upper INT DECLARE @Low ...