你真的懂select吗??
生活随笔
收集整理的這篇文章主要介紹了
你真的懂select吗??
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
只要接觸過c/c++網(wǎng)路編程人都可能會知道select io 模式,網(wǎng)絡(luò)書籍都說 fd_set {int num; SOCKET arr[64]} 有所限制,因為數(shù)組的長度只有64,那么超過64你就不能放,要么你就是用多線程分別實用select.。
一些書籍通過改定義宏 使數(shù)組的長度變長,但也不實用,不能動態(tài)的變化,我總不能定一個非常的長的長度,畢竟是在棧上。我就在想那么select完全只能在客戶端使用,而且套接字還不能超過64。那這不就是一個軟肋嗎??一直對這個有一個迷惑。。。。。后來,自己看到了libevent的源代碼發(fā)現(xiàn)他也用的是select。。看別人說這個庫,輕輕松松處理上萬個套接字,我就在想select不是有限制嗎??他是怎么做到。。。。。。
看了源代碼,我明白了。他只是用對上存放SOCKET的句柄。。我們看一下他的新定義結(jié)構(gòu)體。struct win_fd_set { u_int fd_count; SOCKET fd_array[1];};這個就是新定義結(jié)構(gòu)體,跟原來稍微有點變化只是把64改為1,有些同學(xué)可能見多很多這樣的寫法,這種寫法我也在一些項目使用了。這種寫法可以fd_array動態(tài)變化。
win_fd_set * Set = (win_fd_set*)malloc(sizeof(win_fd_set) + sizoef(SCOEKT) * 10);
Set->fd_array 可以放11 個 SOCKET,因為我的內(nèi)存大小足夠放11個SOCKET。
請記住內(nèi)存是沒有數(shù)據(jù)格式,只要足夠大小,隨便你怎么放。數(shù)據(jù)格式只是方便我們管理和處理數(shù)據(jù)而已。
這樣就解決64個大小限制。。我其實一直很好奇為什么中國書籍都是一樣的,libevent已經(jīng)出來好久了,但也沒有看到有人說這一點,可能是高手們都不屑。
現(xiàn)在漸漸喜歡看開源的代碼,不喜歡看書籍了,喜歡在代碼中學(xué)習(xí)他們是怎么組織一個好項目。
有時候感慨:高手用c 寫著漂亮的c++代碼,而我等菜鳥卻用c++ 寫丑陋的c代碼。。我順便把他整個定義結(jié)構(gòu)和函數(shù)給大家貼出來,免大家還要自己去下libevent,不過推薦沒有看過libevent同學(xué),可以稍微看一下。? 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?????????else110?????????????ent2->write_pos_plus1?=?i+1;111?????}112?????return?(0);113?}114?115?#define?NEVENT?32116?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_count137?????????=?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?int154?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?int179?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?void196?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?int214?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?void298?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?}
總結(jié)
以上是生活随笔為你收集整理的你真的懂select吗??的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux网络编程 五种I/O 模式及s
- 下一篇: #ifdef,#else,#if,#en