回覆列表
  • 1 # 使用者196731058643

    我覺得只有邊沿觸發才必須設定為非阻塞。

    邊沿觸發的問題:

    1. sockfd 的邊緣觸發,高併發時,如果沒有一次處理全部請求,則會出現客戶端連線不上的問題。不需要討論 sockfd 是否阻塞,因為 epoll_wait() 返回的必定是已經就緒的連線,所以不管是阻塞還是非阻塞,accept() 都會立即返回。

    2. 阻塞 connfd 的邊緣觸發,如果不一次性讀取一個事件上的資料,會干擾下一個事件,所以必須在讀取資料的外部套一層迴圈,這樣才能完整的處理資料。但是外層套迴圈之後會導致另外一個問題:處理完資料之後,程式會一直卡在 recv() 函式上,因為是阻塞 IO,如果沒資料可讀,它會一直等在那裡,直到有資料可讀。但是這個時候,如果用另一個客戶端去連線伺服器,伺服器就不能受理這個新的客戶端了。

    3. 非阻塞 connfd 的邊緣觸發,和阻塞版本一樣,必須在讀取資料的外部套一層迴圈,這樣才能完整的處理資料。因為非阻塞 IO 如果沒有資料可讀時,會立即返回,並設定 errno。這裡我們根據 EAGAIN 和 EWOULDBLOCK 來判斷資料是否全部讀取完畢了,如果讀取完畢,就會正常退出迴圈了。

    總結一下:

    1. 對於監聽的 sockfd,最好使用水平觸發模式,邊緣觸發模式會導致高併發情況下,有的客戶端會連線不上。如果非要使用邊緣觸發,可以用 while 來迴圈 accept()。

    2. 對於讀寫的 connfd,水平觸發模式下,阻塞和非阻塞效果都一樣,建議設定非阻塞。

    3. 對於讀寫的 connfd,邊緣觸發模式下,必須使用非阻塞 IO,並要求一次性地完整讀寫全部資料。

  • 中秋節和大豐收的關聯?
  • 伺服電機與步進電機在用途上的區別是什麼啊?