说明:当客户端连接数超过64个的时候,每次最多select64个,但每一帧可以select多次,理论上可以突破fd个数的限制

.h

  1. #ifndef _MODULE_SELECT_H_
  2. #define _MODULE_SELECT_H_
  3. #include "platform/platform.h"
  4.  
  5. class CModuleSelect
  6. {
  7. public:
  8. CModuleSelect();
  9. ~CModuleSelect();
  10. public:
  11. int32_t Initialize();
  12. int32_t Uninitialize();
  13. void ProcessEvent(uint32_t nTimeUsec);
  14. public:
  15. int32_t AddFd(int32_t fd);
  16. int32_t DelFd(uint32_t index);
  17. protected:
  18. void FDSet(int32_t fd)
  19. {
  20. FD_SET(fd, &readfds); FD_SET(fd, &writefds); FD_SET(fd, &errorfds);
  21. if (fd + > maxfdp){ maxfdp = fd + ; }
  22. }
  23. void FDZero()
  24. {
  25. FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&errorfds);
  26. maxfdp = ;
  27. }
  28. void FDClear(int32_t fd)
  29. {
  30. FD_CLR(fd, &readfds); FD_CLR(fd, &writefds); FD_CLR(fd, &errorfds);
  31. };
  32. private:
  33. int32_t sListen;
  34. // fd_set for select
  35. int32_t maxfdp;
  36. struct fd_set readfds, writefds, errorfds;
  37. // all used fd
  38. uint32_t unFdSize;
  39. int32_t *arrFd;
  40. };
  41.  
  42. #endif

.cpp

  1. #include "module_select.h"
  2. #include "common/common.h"
  3.  
  4. CModuleSelect::CModuleSelect()
  5. {
  6. unFdSize = ;
  7. arrFd = new int32_t[unMaxFdSize];
  8. }
  9.  
  10. CModuleSelect::~CModuleSelect()
  11. {
  12. Uninitialize();
  13. }
  14.  
  15. int32_t CModuleSelect::Initialize()
  16. {
  17. WSADATA wsaData;
  18. int32_t nRet = WSAStartup(0x0202, &wsaData);
  19. if (nRet != S_OK){ return WSAGetLastError(); }
  20. sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  21. nRet = AddFd(sListen);
  22. if (nRet != S_OK){ return nRet; }
  23.  
  24. SOCKADDR_IN addrLocal;
  25. addrLocal.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
  26. addrLocal.sin_family = AF_INET;
  27. addrLocal.sin_port = htons(nPort);
  28.  
  29. // bind
  30. nRet = bind(sListen, (struct sockaddr*)&addrLocal, sizeof(SOCKADDR_IN));
  31. if (nRet != S_OK){ return WSAGetLastError(); }
  32.  
  33. // listen
  34. nRet = listen(sListen, );
  35. if (nRet != S_OK){ return WSAGetLastError(); }
  36. printf("listen:%d\n", sListen);
  37. return S_OK;
  38. }
  39.  
  40. void CModuleSelect::ProcessEvent(uint32_t nTimeUsec)
  41. {
  42. int32_t nRet = S_OK;
  43. static struct timeval timeout;
  44. timeout.tv_sec = nTimeUsec / ;
  45. timeout.tv_usec = nTimeUsec % ;
  46.  
  47. static int32_t addrSize = sizeof(SOCKADDR_IN);
  48. static char buf[];
  49. static SOCKADDR_IN addrRemote;
  50. // select all used fd
  51. uint32_t unStartPos = , unEndPos = ;
  52. do
  53. {
  54. // reset fd_set
  55. FDZero();
  56. // fd_set size limited by 'FD_SETSIZE'
  57. for (uint32_t i = ; i < FD_SETSIZE && unEndPos < unFdSize; ++i)
  58. {
  59. FDSet(arrFd[unEndPos++]);
  60. }
  61. nRet = select(maxfdp, &readfds, &writefds, &errorfds, &timeout);
  62. // select error
  63. if (nRet == -)
  64. {
  65. int32_t nError = WSAGetLastError();
  66. perrors("select error,nRet=%d,info=%s\n", nError, strerror(nError));
  67. exit();
  68. }
  69. // time out ,nothing happened
  70. else if (nRet == )
  71. {
  72. printf(".");
  73. continue;
  74. }
  75. // some thing happened
  76. else if (nRet > )
  77. {
  78. // check events
  79. for (uint32_t i = unStartPos; i < unEndPos; ++i)
  80. {
  81. // read events
  82. if ( FD_ISSET(arrFd[i],&readfds) )
  83. {
  84. printf("[%d]:read = %d\n",i,arrFd[i]);
  85. if (sListen == arrFd[i])
  86. {
  87. nRet = accept(sListen, (struct sockaddr*)&addrRemote, &addrSize);
  88. printf("Accepted client:%s:%d\n", inet_ntoa(addrRemote.sin_addr), ntohs(addrRemote.sin_port));
  89. AddFd(nRet);
  90. }
  91. else
  92. {
  93. nRet = recv(arrFd[i], buf, , );
  94. if (nRet == || nRet == SOCKET_ERROR && WSAGetLastError() == WSAECONNRESET)
  95. {
  96. // client close
  97. DelFd(i);
  98. }
  99. else
  100. {
  101. // received correct data from client
  102. buf[nRet] = '\0';
  103. send(arrFd[i], buf, strlen(buf), );
  104. }
  105. }
  106. }
  107. // write events
  108. else if (FD_ISSET(arrFd[i], &writefds))
  109. {
  110. Sleep();
  111. //printf("write = %d\n", arrFd[i]);
  112. }
  113. // error events
  114. else if (FD_ISSET(arrFd[i], &errorfds))
  115. {
  116. printf("error = %d\n", arrFd[i]);
  117. }
  118. }
  119. }
  120. // for next loop
  121. unStartPos = unEndPos;
  122. }while (unEndPos < unFdSize);
  123. }
  124.  
  125. int32_t CModuleSelect::Uninitialize()
  126. {
  127. return WSACleanup();
  128. }
  129.  
  130. int32_t CModuleSelect::AddFd(int32_t fd)
  131. {
  132. if (unFdSize < unMaxFdSize)
  133. {
  134. arrFd[unFdSize++] = fd;
  135. return S_OK;
  136. }
  137. return -;
  138. }
  139.  
  140. int32_t CModuleSelect::DelFd(uint32_t index)
  141. {
  142. if (unFdSize > && index > && unFdSize > index)
  143. {
  144. closesocket(arrFd[index]);
  145. arrFd[index] = arrFd[unFdSize - ];
  146. --unFdSize;
  147. }
  148. return S_OK;
  149. }

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. http://love3400wind.blog.163.com/blog/static/7963080120132794359703/

    http://love3400wind.blog.163.com/blog/static/7963080120132794359703/

  2. Mesh系列文章 - 自定义Mesh

    就是在做项目的过程中,有用到三角形的,今天就写一下如何自定义三角形? 先截个图,让大家有个感性认识! //引用 using UnityEngine;        using System.Colle ...

  3. Beat the Spread![HDU1194]

    Beat the Spread! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  4. topcoder 594 DIV2 foxandclassroom

    暴力枚举 1 #include <iostream> #include <vector> #include <string> using namespace std ...

  5. 【TYVJ】1307 联络员(最小生成树)

    http://tyvj.cn/Problem_Show.aspx?id=1307 kruskal裸题.(水题红色警报) #include <cstdio> #include <cst ...

  6. JS实现上下左右四方向无间隙滚动

    想必大家都注意到<marquee>的不循环滚动,所以出现了很多替代脚本,或iframe或JS输出< marquee>,不管怎么做,都略显麻烦.下面说一下这个相对简单的实现思路: ...

  7. 模板引擎freemarker的简单使用教程

    freemarker十分强大,而且不依赖web容器,个人感觉十分好用. 下面直接进主题,freemarker还有什么特性,请找度娘或谷哥~ 一.freemarker生成word 1.创建模板. 我创建 ...

  8. Spring整合Quartz实现持久化、动态设定时间

    一.spring整合 网上一搜有很多整合的方式,这里我采用了其中的一种(暂时还没有对其他的方法研究过). 对于spring的整合其中的任务,spring提供了几个类.接口(这些类都实现了Job接口): ...

  9. ckeditor的详细配置

    CKEditor 3 JavaScript API Documentation : http://docs.cksource.com/ckeditor_api/symbols/CKEDITOR.con ...

  10. Qt5.4 VS2010 Additional Dependancies

    Go to Linker -> General -> Additional LIbrary Directories: qtmaind.libQt5Cored.libQt5Guid.libQ ...