您当前的位置: 首页 > 

phymat.nico

暂无认证

  • 3浏览

    0关注

    1967博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

你真的懂select吗??

phymat.nico 发布时间:2015-03-07 15:05:35 ,浏览量:3

 只要接触过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 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) 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)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;ifd_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 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 readset_out->fd_count) { 267         i = rand() % win32op->readset_out->fd_count; 268          for (j=0; jreadset_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; jexset_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; jwriteset_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 }
关注
打赏
1659628745
查看更多评论
立即登录/注册

微信扫码登录

0.0439s