1. <nobr id="easjo"><address id="easjo"></address></nobr>

      <track id="easjo"><source id="easjo"></source></track>
      1. 
        

      2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
      3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>
          貴州做網站公司
          貴州做網站公司~專業!靠譜!
          10年網站模板開發經驗,熟悉國內外開源網站程序,包括DEDECMS,WordPress,ZBlog,Discuz! 等網站程序,可為您提供網站建設,網站克隆,仿站,網頁設計,網站制作,網站推廣優化等服務。我們專注高端營銷型網站,企業官網,集團官網,自適應網站,手機網站,網絡營銷,網站優化,網站服務器環境搭建以及托管運維等。為客戶提供一站式網站解決方案?。?!

          多路復用_java多路復用

          來源:互聯網轉載 時間:2024-01-29 08:27:05

          目錄

          • 1、說明
            • 1.1、多路復用的幾種機制
          • 2、函數簡介
            • 2.1、select
            • 2.2、poll
            • 2.3、epoll
              • 2.3.1、epoll_create
              • 2.3.2、epoll_ctl
              • 2.3.3、epoll_wait
            • 2.4、其他方法
          • 3、epoll
            • 3.1、LT模式和ET模式
            • 3.2、優缺點

          1、說明

          socket編程的demo中使用的都是最基本的,但是一般不會真正用在項目中的代碼。而實際項目中,需要面臨復雜多變的需求環境,比如有多個socket連接,或者服務需要監聽的時候,可能有很多socket連接進來。面對這種情況,最直接最簡單的想法是,一個socket連接創建一個線程去處理。當然,在socket連接數較少的情況下,這種方式無可厚非,但是如果連接數量較大,就會出現意外情況。

          我們都知道,linux下一個線程默認所占的內存是8M(可以使用ulimit -s查看),那么加入,1000個socket連接,建立1000線程,光線程的開銷就高達8G多,更遑論其他業務還要使用內存了。

          而且,在很多情況下,socket建立連接之后,并不是要一直通信,而是間隔通信,那么占用一個獨立的線程來“照顧”這個連接顯得很不明智。

          針對這種情況,就需要采用多路復用機制,所謂多路復用,就是一個進程見識多個socket描述符,一旦某個socket描述符就緒(可讀寫或者異常)了,就會通知應用程序,進行相應的處理。

          1.1、多路復用的幾種機制

          目前的多路復用機制有三種,select、poll 和 epoll。這三種機制各有優劣

          2、函數簡介

          2.1、select

          頭文件和函數聲明:

          #include <sys/select.h>int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);FD_ZERO(int fd, fd_set* fds)   // 清空集合FD_SET(int fd, fd_set* fds)    // 將給定的描述符加入集合FD_ISSET(int fd, fd_set* fds)  // 判斷指定描述符是否在集合中 FD_CLR(int fd, fd_set* fds)    // 將給定的描述符從文件中刪除

          描述:

          監聽多個文件描述符的屬性變化。

          函數返回后,需要便利fd_set來找到就緒的描述符

          參數說明:

          nfds: 需要監聽的描述符的范圍,一般是最大描述符+1,比如,現在需要監聽 0/1/2/3/4/5 這幾個描述符,則參數設置為6,在linux下,值最大是1024

          readfds: 監聽到的可讀的描述符的set,所有可讀的描述符都會存儲到這里

          writefds: 監聽到的可寫的描述符的set

          exceptfds: 監聽到的異常的描述符set

          timeout: select 方法的超時時間,這個參數決定 select 的運行機制,可能有三種值

          1. NULL,設置為空指針,則select阻塞運行
          2. 0,select 非阻塞運行,機制變為輪詢,注意,不是參數傳遞0,參數傳遞0表示NULL
          3. >0,在指定的時間內阻塞,但有事件或者超時之后返回,返回值為有事件的描述符數量

          返回值:

          select 返回有事件的描述符數量,可以在對應的set中找到具體的描述符,錯誤則返回-1

          優點: 跨平臺

          缺點:

          1. 描述符的數量受到限制,比如linux下最大1024;
          2. 每次調用,都需要將set從用戶態復制到內核態,這在描述符多時,開銷很大;
          3. 采用便利輪詢的方式,多了無意義的損耗,比如,只需要監聽99的描述符,但是內核會遍歷0~100的描述符;

          2.2、poll

          頭文件和函數聲明:

          #include <poll.h>int poll (struct pollfd *fds, unsigned int nfds, int timeout);struct pollfd {    int fd;    /* 描述符 */    short events;  /* 需要監聽的事件 */    short revents; /* 實際發生的事件 */};

          函數描述: 監聽多個文件描述符的屬性變化,和select類似,但是有很大區別,使用一個 pollfd 指針來替代 select 的三個set的功能

          參數描述:

          fd: 結構體指針,可以傳入多個結構體,每個結構體都是一個被監聽的描述符

          nfds: 指定傳入的結構體的數量

          timeout: 超時時間,單位毫秒,-1 表示阻塞

          返回值: 返回有事件的描述符數量,函數返回后,需要輪詢來找到發生事件的描述符,錯誤則返回-1

          pollfd 結構體:

          ? fd: 表示描述符

          ? events: 需要監聽的事件掩碼,取值如下

          ? revents: 實際發生的事件掩碼,取值如下

          宏定義

          可作events的值

          可作revents的值

          說明

          POLLIN

          y

          y

          數據可讀

          POLLRDNORM

          y

          y

          普通數據可讀

          POLLRDBAND

          y

          y

          優先數據可讀

          POLLPRI

          y

          y

          緊迫帶數據可讀

          POLLOUT

          y

          y

          數據可寫,不會阻塞

          POLLWRNORM

          y

          y

          普通數據可寫,不會阻塞

          POLLWRBAND

          y

          y

          優先級帶數據可寫,不會阻塞

          POLLMSGSIGPOLL

          y

          y

          消息可用

          非法事件

          宏定義

          可作events的值

          可作revents的值

          說明

          POLLERR

          y

          發生錯誤

          POLLHUP

          y

          發生掛起

          POLLNVAL

          y

          描述不是打開的文件

          POLLIN | POLLPRI 等價于 select 的讀事件,而 POLLIN 等價于 POLLRDNORM | POLLRDBAND

          POLLOUT | POLLWRBAND 等價于 select 的寫事件,而 POLLOUT 等價于 POLLWRNORM

          這些事件不是互斥的,可以同時設置

          優缺點:

          和 select 相比,poll 沒有了數量的限制,但是數量太大也會影響效率

          poll 同樣有著將傳入的描述符從用戶態復制到內核態的缺點,開銷隨著描述符數量的增大而線性增大

          2.3、epoll

          epoll是后來提出的,作為 select 和 poll 的增強版本

          epoll 的操作需要三個接口,頭文件和聲明如下:

          #include <sys/epoll.h> int epoll_create(int size);  int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);  

          2.3.1、epoll_create

          int epoll_create(int size); 

          創建一個 epoll 專用的描述符,size 為監聽的數目

          size 參數并沒有限制 epoll 監聽的描述符的最大限制,而是作為內部分配數據結構的一個建議,linux自動2.6.8版本之后,該參數被忽略,只要大于0就行

          返回一個描述符,使用結束時,需要close(),錯誤則返回-1

          2.3.2、epoll_ctl

          int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

          epoll 的事件注冊,告訴 epoll 要監聽哪些事件

          返回0表示注冊成功,-1表示失敗

          參數:

          epfd: epoll 專用的描述符,由epoll_create() 返回

          op: 該函數的作用,即注冊(EPOLL_CTL_ADD)、修改(EPOLL_CTL_MOD)和刪除(EPOLL_CTL_DEL)

          fd: 需要監聽的描述符

          event: 告訴內核要監聽什么事件,聲明如下:

          // 保存觸發事件的某個文件描述符相關的數據(與具體使用方式有關)  typedefunionepoll_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 */  };  

          epoll_event 中的 events 可以是以下宏定義的集合

          宏定義

          說明

          EPOLLIN

          表示對應的文件描述符可以讀(包括對端 SOCKET 正常關閉)

          EPOLLOUT

          表示對應的文件描述符可以寫

          EPOLLPRI

          表示對應的文件描述符有緊急的數據可讀(這里應該表示有帶外數據到來)

          EPOLLERR

          表示對應的文件描述符發生錯誤

          EPOLLHUP

          表示對應的文件描述符被掛斷

          EPOLLET

          將 EPOLL 設為邊緣觸發(Edge Trigger)模式,這是相對于水平觸發(Level Trigger)來說的

          EPOLLONESHOT

          只監聽一次事件,當監聽完這次事件之后,如果還需要繼續監聽這個 socket 的話,需要再次把這個 socket 加入到 EPOLL 隊列里

          2.3.3、epoll_wait

          int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout); 

          等待 epoll 監聽下的 IO 事件

          參數:

          epfd: epoll 描述符

          events: epoll 會把發生的事件賦值到events中

          maxevents: 表明這個 events 的大小

          timeout: 超時時間,單位毫秒,-1表示阻塞

          返回值: 返回需要處理的事件數目,0表示超時未有事件,-1表示失敗

          2.4、其他方法

          FD_ZERO(fd_set *fdset);//清空一個描述符集合FD_SET(fd_set *fdset, int fd);//添加fd到描述符集合中FD_CLR(fd_set *fdset, int fd);//從描述符集合中刪除一個fdFD_ISSET(int fd,fd_set *fdset);//檢查fd是否在描述符集合中

          3、epoll

          epoll 的工作模式有兩種:LT(level trigger) 和 ET(edge trigger),默認LT模式,區別如下:

          LT模式: 當 epoll_wait 檢測到描述符事件發生,并通知應用程序,應用程序可以不利己處理該事件,下次調用 epoll_wait 時,還是會通知此事件

          ET模式: 當 epoll_wait 檢測到描述符事件發生,并通知應用程序,應用程序必須立即處理該事件。如果不處理,則下次調用時,不會再次通知此事件

          3.1、LT模式和ET模式

          LT模式:

          默認模式,支持阻塞和非阻塞方式,內核會通知事件發生,若果不做任何操作,則內核下次還是會通知,編程不易出錯,select/poll都是這種模式

          ET模式:

          告訴你工作模式,只支持非阻塞。在這種模式下,當描述符從未就緒變為就緒時,內核通過epoll告訴你。然后它會假設你知道文件描述符已經就緒,并且不會再為那個文件描述符發送更多的就緒通知,直到你做了某些操作導致那個文件描述符不再為就緒狀態了(比如,你在發送,接收或者接收請求,或者發送接收的數據少于一定量時導致了一個EWOULDBLOCK 錯誤)。但是請注意,如果一直不對這個fd作IO操作(從而導致它再次變成未就緒),內核不會發送更多的通知(only once)

          ET模式在很大程度上減少了epoll事件被重復觸發的次數,因此效率要比LT模式高。epoll工作在ET模式的時候,必須使用非阻塞套接口,以避免由于一個文件句柄的阻塞讀/阻塞寫操作把處理多個文件描述符的任務餓死。

          在 select/poll中,進程只有在調用一定的方法后,內核才對所有監視的文件描述符進行掃描,而epoll事先通過epoll_ctl()來注冊一 個文件描述符,一旦基于某個文件描述符就緒時,內核會采用類似callback的回調機制,迅速激活這個文件描述符,當進程調用epoll_wait() 時便得到通知。(此處去掉了遍歷文件描述符,而是通過監聽回調的的機制。這正是epoll的魅力所在。)

          3.2、優缺點

          1. 監聽數量不受限制,理論上上限是最大可以打開的文件數目,這個數目一般遠大于2048,linux上可以使用 cat /proc/sys/fs/file-max 命令查看。select的最大缺點就是進程打開的fd是有數量限制的。這對 于連接數量比較大的服務器來說根本不能滿足。雖然也可以選擇多進程的解決方案( Apache就是這樣實現的),不過雖然linux上面創建進程的代價比較小,但仍舊是不可忽視的,加上進程間數據同步遠比不上線程間同步的高效,所以也不是一種完美的方案。
          2. IO的效率不會隨著監視fd的數量的增長而下降。epoll不同于select和poll輪詢的方式,而是通過每個fd定義的回調函數來實現的。只有就緒的fd才會執行回調函數。
          3. 文件描述符只需要復制一次到內核,不需要每一次調用函數都進行文件描述符的內核復制

          如果沒有大量的idle -connection或者dead-connection,epoll的效率并不會比select/poll高很多,但是當遇到大量的idle- connection,就會發現epoll的效率大大高于select/poll。

          168186.html

          標簽:遑論其他-

          網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...

          在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...

          在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...

          蘋果CEO喬布斯身價多少?世界排第幾?如果是凈值的話,蘋果首席執行官史蒂夫·喬布斯以83億美元的凈值在《福布斯》2011年全球富豪榜上排名第110位。與此同時,喬布斯在美國富豪中排名第34位。喬布斯怎么能持有蘋果一半以上的股份?當喬布斯持有蘋果公司11.3%的650萬股股份時,他在被股東趕出蘋果公司后賣掉了這11.3%的股份?,F在喬布斯回來時持有蘋果公司不到1%的股份,大約550萬美元的股份,只占...

          二級路由器設置教程?1. 我們登錄到第二路由器頁面。2. 然后單擊路由器設置按鈕進入設置頁面。3. 在設置頁面中,單擊LAN端口設置。4. 進入LAN設置頁面后,我們選擇手動設置。5. 進入手動設置頁面后,我們將路由器的LAN地址更改為其他網段。6. 更改完成后,單擊保存按鈕。然后將WAN端口設置為與主路由器連接。二級路由wan口如何設置?不要設置靜態,實現二級路由器的構造:第一個路由器的廣域網端...

          懷舊服保險絲哪里獲???可以在諾莫瑞根和荊棘谷的各種機械怪物后面投下引信,這些怪物的等級在30到40之間。魔獸世界懷舊服保險絲怎么得?荊棘谷(41.2,43.3)的微型礦車掉引信概率最高。而灼人峽谷(34.7,51.9)的柯朗克下降率略低,但相對較高。魔獸工程圖紙保險絲哪買?地點:東泉谷王勇鎮工程供應商。如何獲?。簭墓こ坦烫幉少?。過程:點擊U,打開你的信譽列表,殺死王勇鎮的工程供應商。然后跑路,...

          TOP
          国产初高中生视频在线观看|亚洲一区中文|久久亚洲欧美国产精品|黄色网站入口免费进人
          1. <nobr id="easjo"><address id="easjo"></address></nobr>

              <track id="easjo"><source id="easjo"></source></track>
              1. 
                

              2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
              3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>