非同步套接字基礎:多路複用、select函式以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET
系統提供select函式來實現多路複用輸入/輸出模型。原型:
#include sys/time.h>
#include unistd.h>
int select(int maxfd,fd_set *rdset,fd_set *wrset,fd_set *exset,struct timeval *timeout);
引數maxfd是需要監視的最大的檔案描述符值+1;rdset,wrset,exset分別對應於需要檢測的可讀檔案描述符的集合,可寫檔案描述符的集 合及異常檔案描述符的集合。struct timeval結構用於描述一段時間長度,如果在這個時間內,需要監視的描述符沒有事件發生則函式返回,返回值為0。
FD_ZERO,FD_SET,FD_CLR,FD_ISSET: 引數maxfd是需要監視的最大的檔案描述符值+1;rdset,wrset,exset分別對應於需要檢測的可讀檔案描述符的集合,可寫檔案描述符的集 合及異常檔案描述符的集合。struct timeval結構用於描述一段時間長度,如果在這個時間內,需要監視的描述符沒有事件發生則函式返回,返回值為0。
FD_ZERO,FD_SET,FD_CLR,FD_ISSET:
FD_ZERO(fd_set *fdset);將指定的檔案描述符集清空,在對檔案描述符集合進行設定前,必須對其進行初始化,如果不清空,由於在系統分配記憶體空間後,通常並不作清空處理,所以結果是不可知的。
FD_SET(fd_set *fdset);用於在檔案描述符集合中增加一個新的檔案描述符。
FD_CLR(fd_set *fdset);用於在檔案描述符集合中刪除一個檔案描述符。
FD_ISSET(int fd,fd_set *fdset);用於測試指定的檔案描述符是否在該集合中。
struct timeval結構:
struct timeval
{
long tv_usec;//minisecond
}
timeout設定情況:
null
0:僅檢測描述符集合的狀態,然後立即返回,並不等待外部事件的發生。
特定的時間值:如果在指定的時間段裡沒有事件發生,select將超時返回。
fd_set
fd_set set;
FD_ZERO(&set); /* 將set清零 */
FD_SET(fd, &set); /* 將fd加入set */
FD_CLR(fd, &set); /* 將fd從set中清除 */
FD_ISSET(fd, &set); /* 如果fd在set中則真*/
多路複用
多路複用的方式是真正實用的伺服器程式,非多路複用的網路程式只能作為學習或著陪測的角色。本文說下個人接觸過的多路複用函式:select/poll/epoll/port。kqueue的*nix系統沒接觸過,估計熟悉了上面四種,kqueue也只是需要熟悉一下而已。
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://www.cppblog.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
}
}
相關推薦
非同步套接字基礎:多路複用、select函式以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET
select函式: 系統提供select函式來實現多路複用輸入/輸出模型。原型: #include sys/time.h> #include unistd.h> int select(int maxfd,f
非同步套接字基礎:select函式以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET
select函式: 系統提供select函式來實現多路複用輸入/輸出模型。原型: #include sys/time.h> #include unistd.h> select函式:
11 非阻塞套接字與IO多路復用(進階)
img 一行 回調 lba let 自己 elf accept error: 1、非阻塞套接字 第一部分 基本IO模型 1.普通套接字實現的服務端的缺陷 一次只能服務一個客戶端! 2.普通套接字實現的服務端的瓶頸!!! accept阻塞! 在沒有新的套接字來之前,不能處
HTTP協議篇(一):多路複用、資料流
管道機制、多路複用 管道機制(Pipelining) HTTP 1.1 引入了管道機制(Pipelining),即客戶端可通過同一個TCP連線同時傳送多個請求。如果客戶端需要請求兩個資源,以前的做法是在同一個TCP連線裡面,先發送A請求,然後等待伺服器做出迴應,收到後再
網路通訊 :IO多路複用之select、poll、epoll詳解
目前支援I/O多路複用的系統呼叫有 select,pselect,poll,epoll,I/O多路複用就是通過一種機制,一個程序可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程式進行相應的讀寫操作。但select,pselect,poll,epoll
Linux網路程式設計---I/O多路複用之select
1.I/O多路複用(IO multiplexing) 我們之前講了I/O多路複用和其他I/O的區別,在這裡,我們再具體討論下I/O多路複用是怎麼工作? I/O 多路複用技術就是為了解決程序或執行緒阻塞到某個 I/O 系統呼叫而出現的技術,使程序不阻塞於某個特定的 I/O 系統呼叫。
Linux IO多路複用之select
Linux IO多路複用之select 首先,我我們來介紹一下什麼是IO多路複用: IO多路複用是指核心一旦發現程序指定的一個或者多個IO條件準備讀取,它就通知該程序。 IO多路複用適用如下場合: 當客戶處理多個描述符時(一般是互動式輸入和網路套介面),
IO 多路複用之select(高效併發伺服器)
一、I/O 多路複用概述 I/O 多路複用技術是為了解決程序或執行緒阻塞到某個 I/O 系統呼叫而出現的技術,使程序不阻塞於某個特定的 I/O 系統呼叫。 select,poll,epoll都是I/O多路複用的機制。I/O多路複用通過一種機制,可以監視多個描述符,一旦某個
嵌入式Linux網路程式設計,I/O多路複用,select()示例,select()客戶端,select()伺服器,單鏈表
文章目錄 1,IO複用select()示例 1.1 select()---net.h 1.2 select()---client.c 1.3 select()---sever.c 1.4 select()---linklist.h
I/O多路複用之select、poll、epoll
很早之前有寫過篇IO多路複用的文章:https://www.cnblogs.com/klcf0220/archive/2013/05/14/3077003.html 參考連結:https://segmentfault.com/a/1190000003063859 select,poll,epoll都是IO多路
Linux多路複用之select/poll/epoll實現原理及優缺點對比
一、select的實現原理 支援阻塞操作的裝置驅動通常會實現一組自身的等待佇列如讀/寫等待佇列用於支援上層(使用者層)所需的BLOCK或NONBLOCK操作。當應用程式通過裝置驅動訪問該裝置時(預設為
IO多路複用之select、poll、epoll詳解
ET(edge-triggered)是高速工作方式,只支援no-block socket。在這種模式下,當描述符從未就緒變為就緒時,核心通過epoll告訴你。然後它會假設你知道檔案描述符已經就緒,並且不會再為那個檔案描述符傳送更多的就緒通知,直到你做了某些操作導致那個檔案描述符不再為就緒狀態了(比如,你在
淺談網路I/O多路複用模型 select & poll & epoll
我們首先需要知道select,poll,epoll都是IO多路複用的機制。I/O多路複用就通過一種機制,可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程式進行相應的讀寫操作。但select,poll,epoll本質上都是同步I/O,因為他們都需要在讀寫事件就緒後自己負責進行讀寫,
IO多路複用之select總結
轉載自 阻塞式I/O程式設計有兩個特點: 一、如果一個發現I\O有輸入,讀取的過程中,另外一個也有了輸入,這時候不會產生任何反應,也就是需要你的程式語句去select的時候才知道有資料輸入。 二、程式去select的時候,如果沒有資料輸入,程式會一直等待,直到有資
Linux下套接字詳解---epoll模式下的IO多路複用伺服器
1 epoll模型簡介 epoll可是當前在Linux下開發大規模併發網路程式的熱門人選,epoll 在Linux2.6核心中正式引入,和select相似,其實都I/O多路複用技術而已,並沒有什麼神祕的。 其實在Linux下設計併發網路程式,向來不缺少方法,比如典型的Apache模型(Proce
Visual C++網路程式設計經典案例詳解 第3章 多執行緒與非同步套接字程式設計 實現執行緒同步 互斥物件 使用API函式操作互斥物件
互斥物件和臨界區物件和事件物件作用一樣 用於實現執行緒同步 互斥物件可以線上程中使用 CreateMutex()建立並返回互斥物件 原型如下 HANDLE CreateMutex( LPSECURITY_ATTIRIBUTES lpMutexAttributes,
Visual C++網路程式設計經典案例詳解 第3章 多執行緒與非同步套接字程式設計 實現執行緒同步 互斥物件 程式的唯一執行
互斥物件可在程序中使用 使用者在程序建立互斥物件實現程式例項唯一執行 建立控制檯工程 #include<windows.h> //包含標頭檔案 #include<stdio.h> in
Visual C++網路程式設計經典案例詳解 第3章 多執行緒與非同步套接字程式設計 程序間通訊 命名管道 命名管道例項
vc新增控制檯工程 名字命名管道例項 新增原始檔 名字 伺服器 #include<windows.h> //包含標頭檔案 #include<stdio.h> int main() {
多路複用與多路分解;UDP報文段格式;套接字和埠號
UDP套接字(目的IP地址,目的埠號),若兩個UDP報文段有不同源IP地址和/或源埠號,但有相同目的IP地址和目的埠號,則這兩個報文段將通過相同的套接字被定向到相同的目的程序。TCP套接字(源IP地址,源埠號,目的IP地址,目的埠號),當一個TCP報文段從網路到達一臺主機時,
Linux下套接字詳解(十)---epoll模式下的IO多路複用伺服器
1 epoll模型簡介 epoll可是當前在Linux下開發大規模併發網路程式的熱門人選,epoll 在Linux2.6核心中正式引入,和select相似,其實都I/O多路複用技術而已,並沒有什麼神祕的。 其實在Linux下設計併發網路程式,向來不缺少