2010-01-06 133 views
3

我不明白在等待調用recv()之後,在非阻塞套接字上調用recv()與阻塞套接字之間的區別是什麼,在select返回之後它已準備好讀取。無論如何,在我看來,像這樣的阻塞套接字永遠不會阻塞。
此外,我聽說一個使用非阻塞套接字的模型是在經過一段時間後,嘗試對它們進行調用(recv/send/etc),而不是使用select之類的東西。這種技術看起來很慢並且比較浪費,比如使用類似select的方法(但是如上所述,我根本沒有達到非阻塞的目的)。這在今天的網絡編程中很常見嗎?帶選擇的非阻塞套接字

回答

1

select,poll,epoll,kqueue等設施目標多套接字/文件描述符處理方案。想象一下,一個帶有數百個同時連接的套接字的重載Web服務器。你怎麼知道什麼時候read以及什麼套接字沒有阻塞一切?

0

如果您在非阻塞套接字上調用read,如果自上次調用read以來沒有收到任何數據,它將立即返回。如果您只有read,並且您想等到有數據可用時,則必須busy wait。這浪費了CPU。

pollselect(和朋友)允許你睡覺,直到有數據要讀取(或寫入,或收到信號等)爲止。

如果您正在做的唯一事情是在該套接字上發送和接收,那麼您可能只需使用非阻塞套接字。當你有其他事情要做的時候,異步是很重要的,例如更新GUI或處理其他套接字。

0

對於你的第一個問題,在這種情況下沒有任何區別。唯一的區別是當沒有什麼可讀的時候他們會做什麼。既然你在調用recv()之前檢查它,你將看不到任何區別。

對於第二個問題,我在所有庫中看到的方式是使用select,poll,epoll,kqueue來測試數據是否可用。選擇方法是最老的,從性能角度來看最不理想(特別是對於管理大量連接)。

+0

'select'可以指示一個套接字是可讀的,但是當它去讀取它時,它沒有可用的數據。這是一個非常有邊緣的情況,但它可能發生在像校驗和不好的數據包一樣的情況下(只有當應用程序讀取數據時纔會檢查它)。 – caf 2010-01-11 03:44:39

3

對於執行大容量I/O的所有不同選項(稱爲The C10K Problem)都有很好的概述。它有很多不同的選擇,至少在2006年

從它引用的一個相當完整的調查顯示,在非阻塞套接字使用select的話題:

注:這是特別重要的是要記住,來自內核的準備就緒通知只是一個提示;當您嘗試從中讀取文件描述符可能不會準備好。這就是爲什麼在使用準備就緒通知時使用非阻塞模式非常重要。

是的,你可以使用非阻塞套接字,然後有一個循環,等待如果沒有準備好,但相比使用類似select或更現代的替代品(epoll的一個相當浪費,kqueue等)。我想不出任何人真的想要這樣做的原因;所有select類似的選項都有能力設置超時,所以你可以在一段時間後喚醒來執行一些常規操作。我想,如果你正在做一些相當CPU密集的事情,比如運行一個視頻遊戲,你可能不想睡覺,而是保持計算,同時使用非阻塞套接字定期檢查I/O。

+2

當需要低延遲時,這種繁忙的循環是相當普遍的,浪費週期被一些$$$覆蓋(閱讀 - 金融業:)。這個想法基本上不是讓內核在syscall內部休眠,因此至少關閉兩個上下文切換。 – 2010-01-07 20:35:22

+0

夠公平的。所以你可能會這樣做有一些原因,但是對於大多數應用程序,你通常希望使用'select'循環。 – 2010-01-07 21:56:43