• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 25,  comments - 36,  trackbacks - 0
               只要接觸過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 *basestruct 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 *outconst 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 *basestruct 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 }
            posted on 2013-12-10 14:20 小魚兒 閱讀(6965) 評論(1)  編輯 收藏 引用

            FeedBack:
            # re: 你真的懂select嗎??[未登錄]
            2015-03-04 17:23 | Charles
            寫的很棒誒  回復  更多評論
              
            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            常用鏈接

            留言簿(4)

            隨筆檔案(25)

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            94久久国产乱子伦精品免费| 一本色综合网久久| 国产成人无码精品久久久久免费 | 精品水蜜桃久久久久久久| 国产精品内射久久久久欢欢 | 亚洲国产精品久久久天堂| 色8久久人人97超碰香蕉987| 久久精品国产一区| 一本久久综合亚洲鲁鲁五月天| 亚洲精品tv久久久久久久久| 精品国产热久久久福利| 丁香色欲久久久久久综合网| 国产精品成人久久久久三级午夜电影| 久久天天躁狠狠躁夜夜躁2014| 久久综合噜噜激激的五月天| 久久亚洲AV无码西西人体| 久久99精品久久只有精品| 国产精品久久久香蕉| 亚洲嫩草影院久久精品| 天天躁日日躁狠狠久久| 香蕉久久夜色精品国产尤物| 久久99精品久久久久久野外| 久久777国产线看观看精品| 亚洲中文字幕无码久久精品1| 色播久久人人爽人人爽人人片aV | 国产精品综合久久第一页| 久久久www免费人成精品| 久久婷婷人人澡人人| 精品久久久久久国产免费了| 久久91精品国产91久久小草| 久久亚洲AV成人出白浆无码国产| 狠狠综合久久综合88亚洲| 亚洲精品国产自在久久| 无码人妻久久一区二区三区蜜桃| 日本精品久久久中文字幕| 久久91精品国产91久久户| 国产精品九九九久久九九| 粉嫩小泬无遮挡久久久久久| 狠狠色丁香久久婷婷综合五月| 久久久久久亚洲AV无码专区| 久久久女人与动物群交毛片|