套接字編程中的select函數(shù)是一個(gè)比較重要的概念,是epoll函數(shù)的早期版本酝碳,是實(shí)現(xiàn)I/O復(fù)用的關(guān)鍵方法。在對(duì)這個(gè)方法的了解過(guò)程中击敌,走了一些彎路,由于select一直與并發(fā)圣蝎,異步等字眼聯(lián)系在一起衡瓶,總覺得select是不阻塞的,事實(shí)上它本身是阻塞的关面。當(dāng)我苦苦在網(wǎng)上搜索答案卻相互矛盾的時(shí)候,我知道是時(shí)候冷靜下來(lái)喝一口水等太,思考自己是否還適合干這一行。不對(duì)奠宜,是是時(shí)候找一本權(quán)威的書籍翻閱一下了瞻想。
阻塞I/O模型
首先需要了解的是socket阻塞的概念,我們知道socket的讀寫操作并不是直接向網(wǎng)絡(luò)中讀寫蘑险,而是向本地的網(wǎng)絡(luò)緩沖區(qū)中讀寫,每一個(gè)socket會(huì)被分配一個(gè)讀和一個(gè)寫緩沖區(qū)泼差,如果當(dāng)我們希望讀取數(shù)據(jù)和屎,但是緩沖區(qū)中還沒有數(shù)據(jù)的時(shí)候春瞬,那么讀方法(recv)會(huì)被阻塞知道有足夠的數(shù)據(jù)可以接受,那么這個(gè)過(guò)程中進(jìn)程會(huì)被阻塞宽气,你的程序不能干別的,只能等绪氛。在《UNIX網(wǎng)絡(luò)編程》一書中涝影,用這樣的圖來(lái)表示這個(gè)過(guò)程。
I/O復(fù)用模型
第二個(gè)需要了解的概念是I/O復(fù)用序目,因?yàn)閟elect伯襟,包括poll和epoll都是實(shí)現(xiàn)這種模型的機(jī)制,我不明白為什么要叫I/O復(fù)用姆怪,但是它的好處是進(jìn)程阻塞與select函數(shù)澡绩,而不是阻塞于真正的I/O系統(tǒng)調(diào)用肥卡,那么這個(gè)過(guò)程同樣書中描述為
看兩張圖昙读,好像復(fù)用并沒有什么優(yōu)越性,因?yàn)樗瑯右枞却钡皆诒O(jiān)聽的socket列表中有socket讀或?qū)懖僮鞣祷芈搿r(shí)間上好像并沒有什么差別。
select的優(yōu)越性
select的優(yōu)越性主要表現(xiàn)在它可以實(shí)現(xiàn)一個(gè)線程監(jiān)聽多個(gè)socket句柄艺沼,而阻塞模型則需要多線程來(lái)達(dá)到這個(gè)目的蕴掏,所以在并發(fā)的大量請(qǐng)求的情況下,這樣是能節(jié)省很多開銷的挽荡。還有在設(shè)置好timeout后即供,超過(guò)這個(gè)時(shí)間select將不再阻塞,會(huì)返回錯(cuò)誤逗嫡,這樣可以接著執(zhí)行別的操作,一定程度上能達(dá)到異步的目的延窜。所以你看抹锄,這樣就和并發(fā)和異步聯(lián)系上了。
結(jié)尾
還有很多問(wèn)題比方說(shuō)select監(jiān)聽多套接字機(jī)制伙单,輪詢的方法,就不探討了谋减,有興趣可以自己看下扫沼。