青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

CppExplore

一切像霧像雨又像風

  C++博客 :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
  29 隨筆 :: 0 文章 :: 280 評論 :: 0 Trackbacks

作者:CppExplore 網址:http://m.shnenglu.com/CppExplore/
多路復用的方式是真正實用的服務器程序,非多路復用的網絡程序只能作為學習或著陪測的角色。本文說下個人接觸過的多路復用函數:select/poll/epoll/port。kqueue的*nix系統沒接觸過,估計熟悉了上面四種,kqueue也只是需要熟悉一下而已。
一、select模型
select原型:

int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);

其中參數n表示監控的所有fd中最大值+1。
和select模型緊密結合的四個宏,含義不解釋了:

FD_CLR(int fd, fd_set *set);
FD_ISSET(
int fd, fd_set *set);
FD_SET(
int fd, fd_set *set);
FD_ZERO(fd_set 
*set);

理解select模型的關鍵在于理解fd_set,為說明方便,取fd_set長度為1字節,fd_set中的每一bit可以對應一個文件描述符fd。則1字節長的fd_set最大可以對應8個fd。
(1)執行fd_set set; FD_ZERO(&set);則set用位表示是0000,0000。
(2)若fd=5,執行FD_SET(fd,&set);后set變為0001,0000(第5位置為1)
(3)若再加入fd=2,fd=1,則set變為0001,0011
(4)執行select(6,&set,0,0,0)阻塞等待
(5)若fd=1,fd=2上都發生可讀事件,則select返回,此時set變為0000,0011。注意:沒有事件發生的fd=5被清空。

基于上面的討論,可以輕松得出select模型的特點:
(1)可監控的文件描述符個數取決與sizeof(fd_set)的值。我這邊服務器上sizeof(fd_set)=512,每bit表示一個文件描述符,則我服務器上支持的最大文件描述符是512*8=4096。據說可調,另有說雖然可調,但調整上限受于編譯內核時的變量值。本人對調整fd_set的大小不太感興趣,參考http://m.shnenglu.com/CppExplore/archive/2008/03/21/45061.html中的模型2(1)可以有效突破select可監控的文件描述符上限。
(2)將fd加入select監控集的同時,還要再使用一個數據結構array保存放到select監控集中的fd,一是用于再select返回后,array作為源數據和fd_set進行FD_ISSET判斷。二是select返回后會把以前加入的但并無事件發生的fd清空,則每次開始select前都要重新從array取得fd逐一加入(FD_ZERO最先),掃描array的同時取得fd最大值maxfd,用于select的第一個參數。
(3)可見select模型必須在select前循環array(加fd,取maxfd),select返回后循環array(FD_ISSET判斷是否有時間發生)。

下面給一個偽碼說明基本select模型的服務器模型:

array[slect_len];
nSock
=0;
array[nSock
++]=listen_fd;(之前listen port已綁定并listen)
maxfd
=listen_fd;
while{
   FD_ZERO(
&set);
   foreach (fd in array) 
   
{
       fd大于maxfd,則maxfd
=fd
       FD_SET(fd,
&set)
   }

   res=select(maxfd
+1,&set,0,0,0);
   
if(FD_ISSET(listen_fd,&set))
   
{
       newfd
=accept(listen_fd);
       array[nsock
++]=newfd;
            if(--res<=0) continue
   }

   foreach 下標1開始 (fd in array) 
   
{
       
if(FD_ISSET(fd,&set))
          執行讀等相關操作
          如果錯誤或者關閉,則要刪除該fd,將array中相應位置和最后一個元素互換就好,nsock減一
             if(--res<=0) continue

   }

}

二、poll模型
poll原型:

int poll(struct pollfd *ufds, unsigned int nfds, int timeout);
struct pollfd 
{
                       
int fd;           /* file descriptor */
                       
short events;     /* requested events */
                       
short revents;    /* returned events */
               }
;

和select相比,兩大改進:
(1)不再有fd個數的上限限制,可以將參數ufds想象成棧低指針,nfds是棧中元素個數,該棧可以無限制增長
(2)引入pollfd結構,將fd信息、需要監控的事件、返回的事件分開保存,則poll返回后不會丟失fd信息和需要監控的事件信息,也就省略了select模型中前面的循環操作,返回后的循環仍然不可避免。另每次poll阻塞操作都會自動把上次的revents清空。
poll的服務器模型偽碼:

struct pollfd fds[POLL_LEN];
unsigned 
int nfds=0;
fds[
0].fd=server_sockfd;
fds[
0].events=POLLIN|POLLPRI;
nfds
++;
while{
  res=poll(fds,nfds,
-1);
  
if(fds[0].revents&(POLLIN|POLLPRI)){執行accept并加入fds中,if(--res<=0)continue}
  循環之后的fds,
if(fds[i].revents&(POLLIN|POLLERR )){操作略if(--res<=0)continue}
}
注意select和poll中res的檢測,可有效減少循環的次數,這也是大量死連接存在時,select和poll性能下降厲害的原因。

三、epoll模型

epoll阻塞操作的原型:

int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout)
epoll引入了新的結構epoll_event。
typedef union epoll_data 
{
                 
void *ptr;
                 
int fd;
                 __uint32_t u32;
                 __uint64_t u64;
            }
 epoll_data_t;

            struct epoll_event 
{
                 __uint32_t events;  
/* Epoll events */
                 epoll_data_t data;  
/* User data variable */
            }
;

與以上模型的優點:
(1)它保留了poll的兩個相對與select的優點
(2)epoll_wait的參數events作為出參,直接返回了有事件發生的fd,epoll_wait的返回值既是發生事件的個數,省略了poll中返回之后的循環操作。
(3)不再象select、poll一樣將標識符局限于fd,epoll中可以將標識符擴大為指針,大大增加了epoll模型下的靈活性。
epoll的服務器模型偽碼:

epollfd=epoll_create(EPOLL_LEN);
epoll_ctl(epollfd,EPOLL_CTL_ADD,server_sockfd,
&ev)
struct epoll_event events[EPOLL_MAX_EVENT];
while
{
nfds
=epoll_wait(epollfd,events,EPOLL_MAX_EVENT,-1);
循環nfds,是server_sockfd則accept,否則執行響應操作
}

epoll使用中的問題:
(1)epoll_ctl的EPOLL_CTL_DEL操作中,最后一個參數是無意義的,但是在小版本號過低的2.6內核下要求最后一個參數一定非NULL,否則返回失敗,并且返回的errno在man epoll_ctl中不存在,因此安全期間,保證epoll_ctl的最后一個參數總非NULLL。
(2)如果一個fd(比如管道)的事件導致了另一個fd2的刪除,則必須掃描返回結果集中是否有fd2,有則在結果集中刪除,避免沖突。
(3)有文章說epoll在G網環境下性能會低于poll/select,看有些測試,給出的拐點在2w/s并發之后,我本人的工作范圍不可能達到這么高的并發,個人在測試性能的時候最大也是取的1w/s的并發,一個是因為系統單進程允許打開的文件描述符最大值,4w的數字太高了,另一個就是我這邊服務器的性能達不到那么高的性能,極限1.7w/s的響應,那測試的數據竟然在2w并發的時候還有2w的響應,不知道是什么硬件配置。或許等有了G網的環境,會關注epoll高并發下的性能下降


(4)epoll的LT和ET性能的差異,我測試的數據表明兩者性能相當,“使用epoll就是為了高性能,就是要使用ET模式”這個說法是站不住腳的。個人傾向于使用LT模式,編程簡單、安全。

四、port模型
port則和epoll非常接近,不需要前后的兩次掃描,直接返回有事件的結果,可以象epoll一樣綁定指針,不同點是
(1)epoll可以返回多個事件,而port一次只返回一個(port_getn可以返回多個,但是在不到指定的n值時,等待直到達到n個)
(2)port返回的結果會自動port_dissociate,如果要再次監控,需要重新port_associate
這個就不多說了。

可以看出select-->poll-->epoll/port的演化路線:
(1)從readset、writeset等分離到 將讀寫事件集中到統一的結構
(2)從阻塞操作前后的兩次循環 到 之后的一次循環  到精確返回有事件發生的fd
(3)從只能綁定fd信息,到可以綁定指針結構信息

五、抽象接口
綜合以上多路復用函數的特點,可以進行統一的封裝,這里給出我封裝的接口,也算是給一個思路:

 virtual int init()=0;
 virtual 
int wait()=0;
 virtual 
void * next_result()=0;
 virtual 
void delete_from_results(void * data)=0;
 virtual 
void * get_data(void * event)=0;
 virtual 
int get_event(void * event)=0;
 virtual 
int add_data(int fd,XPollData * data)=0;
 virtual 
int delete_data(int fd,XPollData *data)=0;
 virtual 
int change_data(int fd,XPollData *data)=0;
 virtual 
int reset_data(int fd,XPollData *data)=0;

使用的時候就是先init,再wait,再循環執行next_result直到空,每個result,使用get_data和get_event挨個處理,如果某個fd引起另一個fd關閉,調delete_from_results(除epoll,其它都直接return),處理完reset_data(select和port用,poll/epoll直接return)。

posted on 2008-04-30 17:23 cppexplore 閱讀(8357) 評論(8)  編輯 收藏 引用

評論

# re: 【原創】系統設計之 網絡模型(三)多路復用模型[未登錄] 2008-04-30 18:13 true
關注epoll和線程池的結合。  回復  更多評論
  

# re: 【原創】系統設計之 網絡模型(三)多路復用模型[未登錄] 2008-04-30 18:47 CppExplore
@true
可以在上一篇《網絡模型二》http://m.shnenglu.com/CppExplore/archive/2008/03/21/45061.html中跟貼討論新模型,是文中已有的,還是沒有的新模型,本文旨在討論函數本身的差異。
epoll和線程池的結合,不是很理解,是epoll單線程后接業務線程,還是epoll本身線程池?epoll本身的話,我想象不出來,結構在可讀狀態的話,新線程epoll_wait還是可讀。并且線程池要求無內蘊狀態,行為的變化來自于外界的輸入參數,莫非是《網絡模型二》中的模型2(1)?
就epoll而言,《網絡模型二》的2模型中,業務線程先不談,單線程的epoll性能就很強,其他模型的測試結果反而有下降。poll/select則不同。
這個話題最好還是在《網絡模型二》中探討,本文不多擴展。  回復  更多評論
  

# re: 【原創】系統設計之 網絡模型(三)多路復用模型[未登錄] 2008-04-30 20:07 true
在《網絡模型二》中回復了,請討論  回復  更多評論
  

# re: 【原創】技術系列之 網絡模型(三)多路復用模型 2008-09-03 12:23 bluesky
(4)epoll的LT和ET性能的差異,我測試的數據表明兩者性能相當,“使用epoll就是為了高性能,就是要使用ET模式”這個說法是站不住腳的。個人傾向于使用LT模式,編程簡單、安全。

epoll LT與ET的性能差別還是蠻大的,LT單臺能撐到10wcpu已經是極限,但ET撐到15w沒啥問題。不過如果應用不要求撐到這么高的在線,那確實LT就可以滿足了。  回復  更多評論
  

# re: 【原創】技術系列之 網絡模型(三)多路復用模型 2008-11-07 11:21 ddd
轉載  回復  更多評論
  

# re: 【原創】技術系列之 網絡模型(三)多路復用模型 2009-02-24 11:11 ff
很高興看到博主的好文,謝謝~~~希望繼續寫下去  回復  更多評論
  

# re: 【原創】技術系列之 網絡模型(三)多路復用模型 2009-06-05 18:09 上海蘇元電氣科技有限公司
上海蘇元電氣科技有限公司,以國內電氣領域服務專家為奮斗目標,自成立以來致力于通過技術創新和優質服務,深化產品內涵,與廣大用戶共贏,與合作伙伴共贏。通過實行營銷專業化,品種規格市場化,堅持自主研發的道路,形成了具有自主知識產權 的“SUWIN”品牌和先進完整成熟的產品設計、制造、銷售技術體系。具備了獨立開發具有國際先進水平的新產品,新技術能力。

也是一種方式,公司剛弄起這些.  回復  更多評論
  

# re: 【原創】技術系列之 網絡模型(三)多路復用模型 2015-03-27 17:18 ckw
文中一、select模型 使用select時也無法突破最大fd=1024的限制啊!  回復  更多評論
  

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            久久国产精品久久国产精品| 欧美99久久| 久久精选视频| 亚洲一区尤物| 在线亚洲成人| 亚洲欧美日韩电影| 久久久www免费人成黑人精品| 亚洲欧美国产不卡| 小辣椒精品导航| 久久久久成人精品免费播放动漫| 久久精品国产第一区二区三区最新章节| 久久av免费一区| 麻豆精品在线观看| 亚洲巨乳在线| 午夜天堂精品久久久久| 久久久久久成人| 欧美全黄视频| 国产一区二区黄色| 亚洲欧洲日韩在线| 午夜精品福利在线| 欧美成人精品高清在线播放| 亚洲精品在线一区二区| 午夜精品一区二区三区在线视| 久久精品国产欧美激情| 欧美人交a欧美精品| 国产午夜精品麻豆| 日韩天堂av| 久久久久久久久久码影片| 亚洲精品一区二区三区99| 久久福利影视| 国产精品视频免费观看www| 亚洲国产一区二区三区青草影视| 亚洲欧美日韩中文在线制服| 欧美激情二区三区| 性色av一区二区三区红粉影视| 欧美大片第1页| 亚洲一区二区三| 久久嫩草精品久久久精品| 国产精品福利网| 亚洲乱码国产乱码精品精可以看| 香蕉av777xxx色综合一区| 欧美二区在线看| 性欧美videos另类喷潮| 欧美日韩精品一本二本三本| 一区二区三区亚洲| 欧美专区第一页| 亚洲婷婷综合久久一本伊一区| 欧美1区视频| 亚洲第一区色| 久久人人爽人人爽爽久久| 一区二区高清| 欧美精品自拍| 日韩午夜高潮| 亚洲国产视频直播| 久久精品99国产精品日本| 国产精品色婷婷久久58| 亚洲一级二级在线| 一本色道久久综合精品竹菊| 欧美片第1页综合| 亚洲精品久久7777| 亚洲国产高清在线| 欧美成人一区二区三区| 亚洲激情在线观看视频免费| 免费日韩成人| 欧美1区视频| 99视频超级精品| 亚洲精品乱码久久久久久黑人| 嫩草成人www欧美| 亚洲精品久久嫩草网站秘色 | 亚洲欧美日韩另类精品一区二区三区| 亚洲第一久久影院| 欧美成人精品激情在线观看| 亚洲激情一区二区| 亚洲久久一区二区| 国产精品狼人久久影院观看方式| 国产精品视频一二| 午夜视频在线观看一区| 亚洲综合色自拍一区| 国产欧美在线观看| 久久一区二区视频| 亚洲人成7777| 欧美日韩一区二区国产| 亚洲午夜久久久久久尤物 | 亚洲欧洲日韩综合二区| 亚洲精品免费一二三区| 欧美午夜精品| 久久精品国产欧美激情| 久久综合福利| 亚洲天堂免费在线观看视频| 亚洲一区亚洲| 亚洲欧洲另类国产综合| 一区二区三区国产在线观看| 国产亚洲一区二区三区| 亚洲高清免费| 一区二区激情小说| 国产无遮挡一区二区三区毛片日本| 久久久免费精品视频| 免费成人黄色片| 性色av一区二区三区在线观看 | 久久美女性网| 在线亚洲观看| 久久精品国产第一区二区三区最新章节 | 一区二区免费在线观看| 国产亚洲激情在线| 最新成人在线| 狠狠爱成人网| 亚洲一区二区三区在线观看视频| 亚洲国产精品小视频| 午夜欧美不卡精品aaaaa| 亚洲免费高清视频| 久久久久综合网| 欧美一区二区三区四区视频| 欧美v亚洲v综合ⅴ国产v| 久久久久久久久岛国免费| 国产精品白丝jk黑袜喷水| 亚洲经典一区| 亚洲欧洲美洲综合色网| 久久国产精品久久久久久电车| 亚洲在线成人精品| 欧美日韩国产区| 亚洲精品久久嫩草网站秘色| 亚洲国产欧美日韩精品| 久久精品人人做人人爽电影蜜月| 亚洲欧美伊人| 国产精品卡一卡二卡三| 9l视频自拍蝌蚪9l视频成人| 亚洲日本中文字幕| 老司机精品久久| 免费观看成人鲁鲁鲁鲁鲁视频| 国产精品欧美精品| 这里只有精品视频在线| 亚洲无线一线二线三线区别av| 欧美高清在线观看| 亚洲最新色图| 欧美激情视频在线免费观看 欧美视频免费一| 久久成人18免费网站| 国产精品视频不卡| 亚洲在线观看免费视频| 午夜精品一区二区三区在线播放| 欧美日韩综合在线| 一本色道久久综合| 亚洲在线一区| 国产精品色在线| 午夜久久久久| 欧美.www| 亚洲毛片av在线| 欧美日韩精品免费观看视一区二区 | 你懂的国产精品永久在线| 海角社区69精品视频| 久久久www成人免费精品| 另类激情亚洲| 亚洲精品看片| 亚洲欧美久久| 欧美中在线观看| 国产一区二区三区高清在线观看| 亚洲欧美国产高清| 久久久综合视频| 在线观看欧美日韩| 欧美日本二区| 亚洲一区二区三区精品在线观看 | 亚洲韩国青草视频| 欧美日韩国产综合久久| 在线亚洲自拍| 久久久久国色av免费看影院| 激情国产一区| 欧美成人a视频| 一区二区三区视频在线观看 | 久久久久久穴| 亚洲另类黄色| 国产精品一区2区| 久久综合99re88久久爱| 日韩午夜激情av| 久久久久久97三级| 妖精成人www高清在线观看| 国产日韩欧美在线播放不卡| 久久久久久午夜| 一区二区三区欧美| 欧美成人免费全部| 亚洲欧美美女| 亚洲精品乱码久久久久久久久| 国产精品高潮粉嫩av| 美女福利精品视频| 亚洲综合99| 亚洲国产精品尤物yw在线观看| 这里只有精品丝袜| 伊甸园精品99久久久久久| 欧美视频三区在线播放| 久久夜色精品| 欧美一区观看| 亚洲私人影院在线观看| 欧美国产日韩视频| 久久三级福利| 亚洲欧美日韩精品久久亚洲区| 亚洲激情在线播放| 一区在线免费| 国产色综合久久| 国产精品免费福利| 欧美日韩网址| 欧美日韩国产区一| 久色婷婷小香蕉久久|