日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

多路 IO 转接 :select 函数

發布時間:2024/9/30 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 多路 IO 转接 :select 函数 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

(1)頭文件:

#include <sys/select.h>

(2)函數原型:

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

(3)參數說明
1)參數1:監聽的所有文件描述符中,最大文件描述符的編號 + 1(即監聽 fd 的總個數)。
2)參數2、3、4:監聽的文件描述符 “是否可讀”、“是否可寫”、“是否異常” 的事件;fd_set代表文件描述符集合,本質是位圖。
3)參數5:設定超時返回結果,若填 NULL 代表永久阻塞,直至有事件發生, 若值為0代表立即返回,非阻塞效果。
這里有兩點要注意的地方:
1)是最常監聽 readfds;writefds 在 epoll 反應堆會使用;exceptfds 一般是內核給系統函數內部使用。
2)以參 2 readfds 為例,并不是我監聽它可讀,它就一定可讀,因此在設計上,都是傳入傳出參數。傳入體現在告訴內核,我想監聽誰是否可讀。傳出體現在通過 select 函數的監聽,內核告訴我具體結果,誰是可讀的。如下圖

(4)返回值:
成功返回所監聽的滿足條件的文件描述符總數量。
例如:
監聽 r:fd1 fd2 fd3
w:fd1 fd3
err:fd1 fd2
滿足條件 r:fd1 fd3
w:fd1 ; err:fd2
則返回值為4 (不要在意 fd1 是否有重復,因為他們屬于不同事件)。
失敗:返回 -1,設置 errno (如果 timeout =0, errno = EAGAIN,代表正常)。
(5)添加監聽的文件描述符函數:

void FD_ZERO(fd_set *set); // 將 set 清空 全部置 0 void FD_SET(int fd, fd_set *set); // 將 fd 添加到 set 中清除(0 變 1) void FD_CLR(int fd, fd_set *set); // 將 fd 從 set 中清除 (1 變 0) int FD_ISSET(int fd, fd_set *set); // 判斷 fd 是否在 set 中(返回 1 表明在)

(6)在返回值中確定哪個文件描述符可讀,哪個可寫

fd_set readfds; // 定義監聽讀事件的文件描述符集合 FD_ZERO(&readfds); // 清空 FD_SET(fd1, &readfds); FD_SET(fd2, &readfds); FD_SET(fd3, &readfds); // 監聽 fd1、fd2、fd3 是否可讀 select(); //以上面結果為例(不考慮 writefds 和 exceptfds)返回值 = 1,但我不知道是誰 //判斷是否在相應集合中 int ret = FD_ISSET(fd1, & readfds); // 發現 ret = 1 說明可讀,意味著客戶端向服務器發送數據,可以通過 fd1 讀取數據 int ret = FD_ISSET(fd2 & readfds); // 顯然 結果 = 0 int ret = FD_ISSET(fd3, & readfds); // 顯然 結果 = 0

(7)select 函數優缺點
優點:一個線程就可以支持多個客戶端(多路 IO 都有這個優點),可以跨平臺(select 獨有)。
缺點:
1)同時監聽文件描述符的上限是 1024 個,注意不是因為打開文件的上限是 1024(上限數可以修改),而是因為在 select 底層實現時候,fd_set使用了宏 FD_SETSIZE = 1024。
2)返回值是一個數量,需要循環遍歷判斷到底誰符合條件,因此高并發少訪問的時候,效率低。
3)監聽集合和滿足監聽條件的集合是同一個集合,select 后會改變原監聽集合,使其無法再次使用,因此,select 前需要將原監聽集合保存。
(8)監聽事件分類:
需要監聽事件分為 2 類,首先一類是建立連接請求(其實是監聽讀事件即服務器寫給我請求,我來讀),另一類是讀寫事件請求 (這些都是建立連接之后的事)。就是說,最開始需要監聽一個讀描述符,有結果,意味著有客戶端請求連接,此時服務器調用 accept 函數便會立即建立連接(雖然 accept 是阻塞函數,但此時不會有阻塞效果),然后再監聽讀寫。

總結

以上是生活随笔為你收集整理的多路 IO 转接 :select 函数的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。