只要接触过c/c++网路编程人都可能会知道select io 模式,网络书籍都说 fd_set {int num; SOCKET arr[64]} 有所限制,因为数组的长度只有64,那么超过64你就不能放,要么你就是用多线程分别实用select.。
一些书籍通过改定义宏 使数组的长度变长,但也不实用,不能动态的变化,我总不能定一个非常的长的长度,毕竟是在栈上。
我就在想那么select完全只能在客户端使用,而且套接字还不能超过64。那这不就是一个软肋吗??一直对这个有一个迷惑。。。。。
后来,自己看到了libevent的源代码发现他也用的是select。。看别人说这个库,轻轻松松处理上万个套接字,我就在想select不是有限制吗??他是怎么做到。。。。。。
看了源代码,我明白了。他只是用对上存放SOCKET的句柄。。我们看一下他的新定义结构体。
struct win_fd_set {
u_int fd_count;
SOCKET fd_array[1];
}; 这个就是新定义结构体,跟原来稍微有点变化只是把64改为1,有些同学可能见多很多这样的写法,这种写法我也在一些项目使用了。这种写法可以fd_array动态变化。 win_fd_set * Set = (win_fd_set*)malloc(sizeof(win_fd_set) + sizoef(SCOEKT) * 10); Set->fd_array 可以放11 个 SOCKET,因为我的内存大小足够放11个SOCKET。 请记住内存是没有数据格式,只要足够大小,随便你怎么放。数据格式只是方便我们管理和处理数据而已。 这样就解决64个大小限制。。我其实一直很好奇为什么中国书籍都是一样的,libevent已经出来好久了,但也没有看到有人说这一点,可能是高手们都不屑。 现在渐渐喜欢看开源的代码,不喜欢看书籍了,喜欢在代码中学习他们是怎么组织一个好项目。 有时候感慨:高手用c 写着漂亮的c++代码,而我等菜鸟却用c++ 写丑陋的c代码。。 我顺便把他整个定义结构和函数给大家贴出来,免大家还要自己去下libevent,不过推荐没有看过libevent同学,可以稍微看一下。

  1 volatile double SIGFPE_REQ = 0.0f;   2    3 struct idx_info {   4     int read_pos_plus1;   5     int write_pos_plus1;   6 };   7    8 struct win32op {   9     unsigned num_fds_in_fd_sets;  10     int resize_out_sets;  11     struct win_fd_set *readset_in;  12     struct win_fd_set *writeset_in;  13     struct win_fd_set *readset_out;  14     struct win_fd_set *writeset_out;  15     struct win_fd_set *exset_out;  16     unsigned signals_are_broken : 1;  17 };  18   19 static void *win32_init(struct event_base *);  20 static int win32_add(struct event_base *, evutil_socket_t, short old, short events, void *_idx);  21 static int win32_del(struct event_base *, evutil_socket_t, short old, short events, void *_idx);  22 static int win32_dispatch(struct event_base *base, struct timeval *);  23 static void win32_dealloc(struct event_base *);  24   25 struct eventop win32ops = {  26     "win32",  27     win32_init,  28     win32_add,  29     win32_del,  30     win32_dispatch,  31     win32_dealloc,  32     0, /* doesn't need reinit */  33     0, /* No features supported. */  34     sizeof(struct idx_info),  35 };  36   37 #define FD_SET_ALLOC_SIZE(n) ((sizeof(struct win_fd_set) + ((n)-1)*sizeof(SOCKET)))  38   39 static int  40 grow_fd_sets(struct win32op *op, unsigned new_num_fds)  41 {  42     size_t size;  43   44     EVUTIL_ASSERT(new_num_fds >= op->readset_in->fd_count &&  45            new_num_fds >= op->writeset_in->fd_count);  46     EVUTIL_ASSERT(new_num_fds >= 1);  47   48     size = FD_SET_ALLOC_SIZE(new_num_fds);  49     if (!(op->readset_in = mm_realloc(op->readset_in, size)))  50         return (-1);  51     if (!(op->writeset_in = mm_realloc(op->writeset_in, size)))  52         return (-1);  53     op->resize_out_sets = 1;  54     op->num_fds_in_fd_sets = new_num_fds;  55     return (0);  56 }  57   58 static int  59 do_fd_set(struct win32op *op, struct idx_info *ent, evutil_socket_t s, int read)  60 {  61     struct win_fd_set *set = read ? op->readset_in : op->writeset_in;  62     if (read) {  63         if (ent->read_pos_plus1 > 0)  64             return (0);  65     } else {  66         if (ent->write_pos_plus1 > 0)  67             return (0);  68     }  69     if (set->fd_count == op->num_fds_in_fd_sets) {  70         if (grow_fd_sets(op, op->num_fds_in_fd_sets*2))  71             return (-1);  72         /* set pointer will have changed and needs reiniting! */  73         set = read ? op->readset_in : op->writeset_in;  74     }  75     set->fd_array[set->fd_count] = s;  76     if (read)  77         ent->read_pos_plus1 = set->fd_count+1;  78     else  79         ent->write_pos_plus1 = set->fd_count+1;  80     return (set->fd_count++);  81 }  82   83 static int  84 do_fd_clear(struct event_base *base,  85             struct win32op *op, struct idx_info *ent, int read)  86 {  87     int i;  88     struct win_fd_set *set = read ? op->readset_in : op->writeset_in;  89     if (read) {  90         i = ent->read_pos_plus1 - 1;  91         ent->read_pos_plus1 = 0;  92     } else {  93         i = ent->write_pos_plus1 - 1;  94         ent->write_pos_plus1 = 0;  95     }  96     if (i < 0)  97         return (0);  98     if (--set->fd_count != (unsigned)i) {  99         struct idx_info *ent2; 100         SOCKET s2; 101         s2 = set->fd_array[i] = set->fd_array[set->fd_count]; 102  103         ent2 = evmap_io_get_fdinfo(&base->io, s2); 104  105         if (!ent2) /* This indicates a bug. */ 106             return (0); 107         if (read) 108             ent2->read_pos_plus1 = i+1; 109         else 110             ent2->write_pos_plus1 = i+1; 111     } 112     return (0); 113 } 114  115 #define NEVENT 32 116 void * 117 win32_init(struct event_base *_base) 118 { 119     struct win32op *winop; 120     size_t size; 121     if (!(winop = mm_calloc(1, sizeof(struct win32op)))) 122         return NULL; 123     winop->num_fds_in_fd_sets = NEVENT; 124     size = FD_SET_ALLOC_SIZE(NEVENT); 125     if (!(winop->readset_in = mm_malloc(size))) 126         goto err; 127     if (!(winop->writeset_in = mm_malloc(size))) 128         goto err; 129     if (!(winop->readset_out = mm_malloc(size))) 130         goto err; 131     if (!(winop->writeset_out = mm_malloc(size))) 132         goto err; 133     if (!(winop->exset_out = mm_malloc(size))) 134         goto err; 135     winop->readset_in->fd_count = winop->writeset_in->fd_count = 0; 136     winop->readset_out->fd_count = winop->writeset_out->fd_count 137         = winop->exset_out->fd_count = 0; 138  139     if (evsig_init(_base) < 0) 140         winop->signals_are_broken = 1; 141  142     return (winop); 143  err: 144     XFREE(winop->readset_in); 145     XFREE(winop->writeset_in); 146     XFREE(winop->readset_out); 147     XFREE(winop->writeset_out); 148     XFREE(winop->exset_out); 149     XFREE(winop); 150     return (NULL); 151 } 152  153 int 154 win32_add(struct event_base *base, evutil_socket_t fd, 155              short old, short events, void *_idx) 156 { 157     struct win32op *win32op = base->evbase; 158     struct idx_info *idx = _idx; 159  160     if ((events & EV_SIGNAL) && win32op->signals_are_broken) 161         return (-1); 162  163     if (!(events & (EV_READ|EV_WRITE))) 164         return (0); 165  166     event_debug(("%s: adding event for %d", __func__, (int)fd)); 167     if (events & EV_READ) { 168         if (do_fd_set(win32op, idx, fd, 1)<0) 169             return (-1); 170     } 171     if (events & EV_WRITE) { 172         if (do_fd_set(win32op, idx, fd, 0)<0) 173             return (-1); 174     } 175     return (0); 176 } 177  178 int 179 win32_del(struct event_base *base, evutil_socket_t fd, short old, short events, 180           void *_idx) 181 { 182     struct win32op *win32op = base->evbase; 183     struct idx_info *idx = _idx; 184  185     event_debug(("%s: Removing event for "EV_SOCK_FMT, 186         __func__, EV_SOCK_ARG(fd))); 187     if (events & EV_READ) 188         do_fd_clear(base, win32op, idx, 1); 189     if (events & EV_WRITE) 190         do_fd_clear(base, win32op, idx, 0); 191  192     return 0; 193 } 194  195 static void 196 fd_set_copy(struct win_fd_set *out, const struct win_fd_set *in) 197 { 198     out->fd_count = in->fd_count; 199     memcpy(out->fd_array, in->fd_array, in->fd_count * (sizeof(SOCKET))); 200 } 201  202 /* 203   static void dump_fd_set(struct win_fd_set *s) 204   { 205   unsigned int i; 206   printf("[ "); 207   for(i=0;i<s->fd_count;++i) 208   printf("%d ",(int)s->fd_array[i]); 209   printf("]\n"); 210   } 211 */ 212  213 int 214 win32_dispatch(struct event_base *base, struct timeval *tv) 215 { 216     struct win32op *win32op = base->evbase; 217     int res = 0; 218     unsigned j, i; 219     int fd_count; 220     SOCKET s; 221  222     if (win32op->resize_out_sets) { 223         size_t size = FD_SET_ALLOC_SIZE(win32op->num_fds_in_fd_sets); 224         if (!(win32op->readset_out = mm_realloc(win32op->readset_out, size))) 225             return (-1); 226         if (!(win32op->exset_out = mm_realloc(win32op->exset_out, size))) 227             return (-1); 228         if (!(win32op->writeset_out = mm_realloc(win32op->writeset_out, size))) 229             return (-1); 230         win32op->resize_out_sets = 0; 231     } 232  233     fd_set_copy(win32op->readset_out, win32op->readset_in); 234     fd_set_copy(win32op->exset_out, win32op->writeset_in); 235     fd_set_copy(win32op->writeset_out, win32op->writeset_in); 236  237     fd_count = 238         (win32op->readset_out->fd_count > win32op->writeset_out->fd_count) ? 239         win32op->readset_out->fd_count : win32op->writeset_out->fd_count; 240  241     if (!fd_count) { 242         long msec = tv ? evutil_tv_to_msec(tv) : LONG_MAX; 243         /* Sleep's DWORD argument is unsigned long */ 244         if (msec < 0) 245             msec = LONG_MAX; 246         /* Windows doesn't like you to call select() with no sockets */ 247         Sleep(msec); 248         return (0); 249     } 250  251     EVBASE_RELEASE_LOCK(base, th_base_lock); 252  253     res = select(fd_count, 254              (struct fd_set*)win32op->readset_out, 255              (struct fd_set*)win32op->writeset_out, 256              (struct fd_set*)win32op->exset_out, tv); 257  258     EVBASE_ACQUIRE_LOCK(base, th_base_lock); 259  260     event_debug(("%s: select returned %d", __func__, res)); 261  262     if (res <= 0) { 263         return res; 264     } 265  266     if (win32op->readset_out->fd_count) { 267         i = rand() % win32op->readset_out->fd_count; 268         for (j=0; j<win32op->readset_out->fd_count; ++j) { 269             if (++i >= win32op->readset_out->fd_count) 270                 i = 0; 271             s = win32op->readset_out->fd_array[i]; 272             evmap_io_active(base, s, EV_READ); 273         } 274     } 275     if (win32op->exset_out->fd_count) { 276         i = rand() % win32op->exset_out->fd_count; 277         for (j=0; j<win32op->exset_out->fd_count; ++j) { 278             if (++i >= win32op->exset_out->fd_count) 279                 i = 0; 280             s = win32op->exset_out->fd_array[i]; 281             evmap_io_active(base, s, EV_WRITE); 282         } 283     } 284     if (win32op->writeset_out->fd_count) { 285         SOCKET s; 286         i = rand() % win32op->writeset_out->fd_count; 287         for (j=0; j<win32op->writeset_out->fd_count; ++j) { 288             if (++i >= win32op->writeset_out->fd_count) 289                 i = 0; 290             s = win32op->writeset_out->fd_array[i]; 291             evmap_io_active(base, s, EV_WRITE); 292         } 293     } 294     return (0); 295 } 296  297 void 298 win32_dealloc(struct event_base *_base) 299 { 300     struct win32op *win32op = _base->evbase; 301  302     evsig_dealloc(_base); 303     if (win32op->readset_in) 304         mm_free(win32op->readset_in); 305     if (win32op->writeset_in) 306         mm_free(win32op->writeset_in); 307     if (win32op->readset_out) 308         mm_free(win32op->readset_out); 309     if (win32op->writeset_out) 310         mm_free(win32op->writeset_out); 311     if (win32op->exset_out) 312         mm_free(win32op->exset_out); 313     /* XXXXX free the tree. */ 314  315     memset(win32op, 0, sizeof(win32op)); 316     mm_free(win32op); 317 }

你真的懂select吗??相关推荐

  1. 你真的懂select Socket模型吗?

    你看到的这个文章来自于http://www.cnblogs.com/ayanmw 转自:http://www.cppblog.com/xvsdf100/archive/2013/12/10/20468 ...

  2. 程序猿修仙之路--数据结构之你是否真的懂数组? c#socket TCP同步网络通信 用lambda表达式树替代反射 ASP.NET MVC如何做一个简单的非法登录拦截...

    程序猿修仙之路--数据结构之你是否真的懂数组? 数据结构 但凡IT江湖侠士,算法与数据结构为必修之课.早有前辈已经明确指出:程序=算法+数据结构  .要想在之后的江湖历练中通关,数据结构必不可少.数据 ...

  3. 【转】先说IEnumerable,我们每天用的foreach你真的懂它吗?

    [转]先说IEnumerable,我们每天用的foreach你真的懂它吗? 我们先思考几个问题: 为什么在foreach中不能修改item的值? 要实现foreach需要满足什么条件? 为什么Linq ...

  4. SQL Server中SELECT会真的阻塞SELECT吗?

    在SQL Server中,我们知道一个SELECT语句执行过程中只会申请一些意向共享锁(IS) 与共享锁(S), 例如我使用SQL Profile跟踪会话86执行SELECT * FROM dbo.T ...

  5. 示波器_你真的懂示波器嘛?面试中会用到的示波器知识

    示波器是电子工程师经常使用到的电子测量仪器,用途十分广泛,可将肉眼看不见的电信号变换成看得见的图像,便于人们研究各种电现象的变化过程.利用示波器能观察各种不同信号幅度随时间变化的波形曲线,还可以用它测 ...

  6. “三次握手,四次挥手”你真的懂吗?

    来源:码农桃花源 解读:"拼多多"被薅的问题出在哪儿?损失将如何买单? 之前有推过一篇不错的干货<TCP之三次握手四次挥手>,前几天有兄弟投稿,开始还以为是同一篇,后经 ...

  7. 【原创】“三次握手,四次挥手”你真的懂吗?

    记得刚毕业找工作面试的时候,经常会被问到:你知道"3次握手,4次挥手"吗?这时候我会"胸有成竹"地"背诵"前期准备好的"答案&qu ...

  8. 你真的懂TensorFlow吗?Tensor是神马?为什么还会Flow?

    本文的ipynb 格式见CSDN下载. 0维张量/标量 标量是一个数字 1维张量/向量 1维张量称为"向量". 2维张量 2维张量称为矩阵 3维张量 公用数据存储在张量 时间序列数 ...

  9. 关于Spring底层原理面试的那些问题,你是不是真的懂Spring?

    转载自  关于Spring底层原理面试的那些问题,你是不是真的懂Spring? 1.什么是 Spring 框架?Spring 框架有哪些主要模块? Spring 框架是一个为 Java 应用程序的开发 ...

最新文章

  1. WCF for .NET CF的一个应用及两个困惑的问题
  2. 计算机合成生物学博士,重磅!Tim Lu 出任 CEO,合成生物学新锐今日闪亮登场
  3. java个人介绍代码_个人项目WC(Java)
  4. pythonrandom模块_python中的random模块
  5. ZipOutputStream 用法 小计
  6. 随机森林算法的随机性_理解随机森林算法的图形指南
  7. Portable项目类型之前多个目标类型共享代码的方式
  8. 鼠标方式自动弹出内容html,html 在一个超链接上面,鼠标移动上去时,也显示一串文字,如何实现...
  9. window.onload与document.ready的区别
  10. 浏览器内核(navigator.appName显示的不是内核信息!!)。
  11. 【CNN】很细的讲解什么以及为什么是卷积(Convolution)!
  12. 返回目录中所有JPG图像的文件名列表
  13. css单行文本和多行文本溢出实现省略号显示
  14. CorelDRAWX4的VBA插件开发(二十九)使用C++制作动态连接库DLL辅助VBA构键强大功能-(3)制作最简单的可供调用的DLL
  15. android javacv,【首发】AndroidStudio配置JavaCV环境
  16. python同构数_用c语言求1到1000的同构数_后端开发
  17. 什么是网络操作系统?网络操作系统具有那些基本功能?
  18. 在VMware上如何创建虚拟机以及安装linux系统
  19. FCPX插件:视频去闪烁插件DEFlicker安装教程
  20. excel表格多列数据中查找重复行数据

热门文章

  1. fatal error C1189: #error : Building MFC application with /MD[d]
  2. Latex论文排版技巧再总结
  3. python list列表排序的两种方法及实例讲解
  4. 如何实现科技论文里面的算法
  5. TypeScript 3.0 新功能介绍(二)
  6. javascript 声明变量var、let、const详解及示例
  7. 太白教你学python---博客分类目录
  8. 重新学.Net[四]——效率和安全
  9. yum 安装服务出现报错收集
  10. 空间谱专题03:时空特性与采样定理