1. 程式人生 > >I/O複用模型之select函式用法——伺服器開發

I/O複用模型之select函式用法——伺服器開發

現在我們介紹另外一種常用併發伺服器開發的技術——select函式I/O複用模型。

先來介紹select及相關的函式:

select函式的作用是監聽指定的多個I/O的檔案描述符,在設定的時間內阻塞,當有一個或者多個I/O埠滿足某個“讀”或者“寫”的條件,則在fd_set型別引數中標記並返回。

int select (
int maxfdp1,      //要監測的I/O描述符範圍:0~maxfdp1-1
fd_set *readset,   //readset是一個值—結果的引數,有一個預設大小為1024位的變數,在呼叫時用它設定哪些描述符需要監聽“讀”,返回時用它識別哪些描述符準備好“讀"。
fd_set *writeset,   //同上這裡監測的是“寫”
fd_set *exceptset,  //同上這裡檢測的是“異常”
const struct timeval * timeout     //設定每次select的最大阻塞時間,若為NULL,則無限阻塞直到滿足返回條件
);

fd_set型別是一個預設大小為1024位的型別,每一位代表一個I/0檔案描述符。例如每個程序預設0、1、2分別表示標準輸入、標準輸出和標準錯誤輸出,所以fd_set型別1024位中0、1、2位分別代表標準輸入、標準輸出和標準錯誤輸出。同理假如程序裡建立了一個監聽socket檔案描述符為3,則fd_set的第3位代表這個監聽sockfd;假如用accept了客戶端連線返回一個sockfd為n,那麼fd_set的第n個位就代表這個sockfd。(因為在一個程序裡,某個I/O口的檔案描述符是唯一的。)

在呼叫時,將需要監聽“讀”的I/O檔案描述符在readset引數對應的“位”裡設為1,同理將需要監聽“寫”的I/O檔案描述符在writeset引數對應的“位”裡設為1,並在maxfdp1裡設定要監聽的最大的檔案描述符+1指定好監聽的範圍。還可以在timeout引數中設定最大的阻塞時間。然後select函式就會在timeout的時間內阻塞,監聽readset、writeset中標記的檔案描述符。當有一個或者多個I/O埠滿足某個“讀”或者“寫”的條件,則將滿足“讀”條件的描述表在readset中對應的位處標記為1。“寫”同理在readset對應位裡標記。

我們就可以根據writeset和readset來找出哪些I/O口準備“讀”或者“寫”了。

select.h標頭檔案提供對fd_set“位“一系列操作函式:

void FD_ZERO(fd_set * fdset);                //將fdset所有“位”置0
void FD_SET(int fd,fd_set * fdset);          //將fdset第fd個位置1
void FD_CLR(int fd,fd_set * fdset);         //將fdset第fd個位置0
void FD_ISSET(int fd,fd_set * fdset);      //判斷fdset第fd個位置是否為1

有了上面的函式,我們就可以這樣操作:(例如想監聽標準輸入I/O和監聽sockfd)

fd_set rdfdset;
int listenfd=socket(AF_INET,SOCK_STREAM,0);
bind(listenfd,(sockaddr *)&servaddr,sizeof(servaddr));
listen(listenfd,10);
FD_ZERO(&rdfdset);
FD_SET(STDIN_FILENO,&rdfdset);
FD_SET(listenfd,&rdfdset);
int maxfdp1=max(STDIN_FILENO,listenfd)+1;
select(maxfdp1,&rdfdset,0,0,0);
if(FD_ISSET(listenfd,&rdfdset))
{
       //do something
}
if(FD_ISSET(STDIN_FILENO,&rdfdset))
{
       //do something
}

我們知道了select函式監聽到某個檔案描述符滿足“讀”或“寫”條件就會返回,那麼怎樣才稱為滿足“讀”或“寫”的條件呢。

一、檔案描述符滿足“讀"條件:(此時用read、readv、recv、recvfrom、recvmsg等讀這個I/O不會阻塞)

1、I/O口接收緩衝區中的資料位元組數大於接收緩衝區低潮限度。(此時呼叫read等函式讀I/O口會返回大於0值)預設低潮限度為1,我們可以利用SO_RCVLOWAT來設定接收緩衝區低潮限度。

2、TCP套介面連線“讀”這一半關閉(利用shutdown),(此時呼叫read等函式讀I/O口會返回等於0值,代表檔案EOF)。

3、監聽套介面準備好(已連線佇列有可用連線,此時呼叫accept函式會馬上返回已連線佇列首部的對端套介面)。

4、套介面錯誤等待處理,(此時呼叫read等函式返回-1)。

二、檔案描述符滿足“寫"條件:(此時用write、writev、send、sendto、sendmsg等讀這個I/O不會阻塞)

1、I/O口傳送緩衝區中的可用空間位元組數大於傳送緩衝區低潮限度。(此時呼叫write等函式寫I/O口會返回大於0值)預設低潮限度為2048,我們可以利用SO_SNDLOWAT來設定傳送緩衝區低潮限度。

2、TCP套介面連線“寫”這一半關閉(利用shutdown)(此時呼叫write等函式寫I/O口會返回等於-1值,併產生SIGPIPE訊號)。

3、套介面錯誤等待處理,(此時呼叫read等函式返回-1)。

根據select函式的特點,簡單的I/O複用併發伺服器流程圖如下:


詳細程式碼待續...

相關推薦

I/O模型select函式用法——伺服器開發

現在我們介紹另外一種常用併發伺服器開發的技術——select函式I/O複用模型。 先來介紹select及相關的函式: select函式的作用是監聽指定的多個I/O的檔案描述符,在設定的時間內阻塞,當有一個或者多個I/O埠滿足某個“讀”或者“寫”的條件,則在fd_set型別

Linux網路程式設計---I/O模型epoll

Linux網路程式設計—I/O複用模型之epoll 1. epoll模型簡介 epoll是Linux多路服用IO介面select/poll的加強版,e對應的英文單詞就是enhancement,中文翻譯為增強,加強,提高,充實的意思。所以epoll模型會顯

I/O-每次呼叫select()前都要重新設定一下待檢測的描述字

select的實現是通過對裝置的輪詢來實現的,每次呼叫FD_ISSET()函式後 ,會把原來待檢測的但是仍沒就緒的描述字清0了。所以,每次呼叫select()前要重新呼叫FD_SET()來設定一下待檢測的描述裝置。 select()的基本知識: select原型: int

伺服器I/O模型實現

Linux下實現I/O服用的系統呼叫主要有select、poll、和epoll。 select和poll的原理實現基本一致,都是在一定的指定時間內監聽使用者感興趣的檔案描述符上的可讀可寫和異常等事件,返回的是整個使用者註冊的事件集合,需要從整個使用者表中輪詢尋找就緒的檔案描

Linux I/Oselect函式詳解

置頂 2017年02月12日 20:50:08 難免有錯_ 閱讀數:7438更多 select函式的功能和呼叫順序 使用select函式時統一監視多個檔案描述符的: 1、 是否存在套接字接收資料? 2、 無需阻塞傳輸資料的套接字有哪些? 3、 哪些套接字發生了

I/Oselect、poll、epoll函式

為了提高程式處理效率和機制,經常需要一個程式可以達到監聽甚至處理多個檔案描述符的效能,為了帶到這種機制我們需要借用I/O複用來實現。I/O複用雖然可以同時處理多個檔案,但是它本身是阻塞的。就是當檔案有多個就緒的時候程式檢測到了才會繼續往下執行,而且在執行的時候如

I/Oselect模型

首先談一談為什麼要引入I/O複用這個概念。當我們必須從兩個檔案描述符中讀取時,我們不能從任一個描述符上進行阻塞讀,否則可能會因為被阻塞在一個檔案描述符的讀操作上而導致另一個描述符即使有資料也無法處理。當然我們也可以通過以下幾種方法解決。下面進行簡單介紹且指出各個

Linux----網路程式設計(I/Oselect系統呼叫)

io_select_ser.c 1. #include <string.h> 2. #include <assert.h> 3. #include <unistd.h> 4. #include <stdio.h> 5. #in

Linux 併發echo伺服器I/Oselect

select 簡介: 將待監聽套接字加入集合,監測,若有資料到來,進行echo,若有新連線請求到來,accept並將對應套接字加入集合 函式: int select(int , fd_set* rd, fd_set* wr , fd_set* except ,

Linux I/Oselect poll epoll模型的介紹及其優缺點的比較

關於I/O多路複用: I/O多路複用(又被稱為“事件驅動”),首先要理解的是,作業系統為你提供了一個功能,當你的某個socket可讀或者可寫的時候,它可以給你一個通知。這樣當配合非阻塞的socket使用時,只有當系統通知我哪個描述符可讀了,我才去執行read操

Linux網路程式設計——I/O函式epoll

https://blog.csdn.net/lianghe_work/article/details/46544567一、epoll概述epoll 是在 2.6 核心中提出的,是之前的 select() 和 poll() 的增強版本。相對於 select() 和 poll()

Linux網路程式設計——tcp併發伺服器I/Oselect

與多執行緒、多程序相比,I/O複用最大的優勢是系統開銷小,系統不需要建立新的程序或者執行緒,也不必維護這些執行緒和程序。 程式碼示例: #include <stdio.h> #include <unistd.h> #include <

Linux網路程式設計——I/Opoll函式

#include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/select.h> #include <sys/time.

I/Oselect

函式功能:在一段時間內,監聽使用者感興趣的檔案描述符上的可讀、可寫與異常事件 函式原型:int select(int nfds,struct fd_set *readfds, struct fd_set *writefds,struct fd_set *execptfds,

基於windows的使用selectI/O回顯伺服器

使用過select函式可以將多個檔案描述符集中到一起監視,集中時也要按照監視項(接收、傳輸、異常)區分。   伺服器端: #include <stdio.h> #include <stdlib.h> #include <WinSock2.h> #de

I/O——select的實現

I/O複用 I/O複用是指一個程序或一個執行緒能夠同時對多對檔案描述符(sockfd)提供服務。那麼伺服器上的程序或執行緒如何對多個檔案描述符統一監聽,當任意一個檔案描述符上有事件發生,其都能及時處理? 有三種方法,今天我著重介紹一下第一種 1.select 2.poll 3.e

Linux高效能伺服器程式設計——I/O select

提出背景     不管是多執行緒,或者多程序,以及執行緒池,程序池。他們都存在一定的效率問題。 1.每個程序或執行緒只能為一個客戶端進行服務,知道該客戶端結束。(如果客戶端在同一時間的訪問數量特別大呢?) 2.當客戶端傳送來資料後,分配執行緒或程序為其服務完後,就要等

I/O——epoll函式

          select函式有效地解決了多個I/O埠的複用問題,但是select函式存在兩個缺陷: 一是程序所能同時開啟的檔案描述符個數受FD_SETSIZE大小的限制; 二是每個select函式返回可用的檔案描述符集合後,應用都必須對所有已註冊的檔案描述符進行遍

I/O——select()、poll()與epoll()的區別

       select()、poll()、epoll()三組I/O複用系統呼叫都可以同時監聽多個檔案描述符。它們將等待由timeout引數指定的超時時間,直到一個或者多個檔案描述符上有事件發生時返回,返回值就是就緒檔案描述符的數量,返回0表示沒有事件發生。 1、sele

網路程式設計中I/Oselect用法

網路程式設計select的用法 select使用流程圖 在網路程式設計中需要新增的程式碼行以及意義 例程 參考文獻及部落格 注:本文對select函式、相關引數及結構體不做解釋 select使用流程