1. 程式人生 > >socket可讀可寫就緒條件

socket可讀可寫就緒條件

轉載自:https://www.cnblogs.com/web21/p/6611284.html

參考 UNIX 網路程式設計卷1》中的《第6 I/O複用》

一、 滿足下列四個條件中的任何一個時,一個套接字準備好讀。

  1. 該套接字接收緩衝區中的資料位元組數大於等於套接字接收快取區低水位。對於TCP和UDP套接字而言,緩衝區低水位的值預設為1。那就意味著,預設情況下,只要緩衝區中有資料,那就是可讀的。我們可以通過使用SO_RCVLOWAT套接字選項(參見setsockopt函式)來設定該套接字的低水位大小。此種描述符就緒(可讀)的情況下,當我們使用read/recv等對該套接字執行讀操作的時候,套接字不會阻塞,而是成功返回一個大於0的值(即可讀資料的大小)。
  2. 該連線的讀半部關閉(也就是接收了FIN的TCP連線)。對這樣的套接字的讀操作,將不會阻塞,而是返回0(也就是EOF)。
  3. 該套接字是一個listen的監聽套接字,並且目前已經完成的連線數不為0。對這樣的套接字進行accept操作通常不會阻塞。
  4. 有一個錯誤套接字待處理。對這樣的套接字的讀操作將不阻塞並返回-1(也就是返回了一個錯誤),同時把errno設定成確切的錯誤條件。這些待處理錯誤(pending error)也可以通過指定SO_ERROR套接字選項呼叫getsockopt獲取並清除。

二、滿足下列四個條件中的任何一個時,一個套接字準備好寫。

  1. 該套接字傳送緩衝區中的可用空間位元組數大於等於套接字傳送快取區低水位標記時,並且該套接字已經成功連線(UDP套接字不需要連線)。
    對於TCP和UDP而言,這個低水位的值預設為2048,而套接字預設的傳送緩衝區大小是8k,這就意味著一般一個套接字連線成功後,就是處於可寫狀態的。我們可以通過SO_SNDLOWAT套接字選項(參見setsockopt函式)來設定這個低水位。此種情況下,我們設定該套接字為非阻塞,對該套接字進行寫操作(如write,send等),將不阻塞,並返回一個正值(例如由傳輸層接受的位元組數,即傳送的資料大小)。
  2. 該連線的寫半部關閉(主動傳送FIN包的TCP連線)。對這樣的套接字的寫操作將會產生SIGPIPE訊號。所以我們的網路程式基本都要自定義處理SIGPIPE訊號。因為SIGPIPE訊號的預設處理方式是程式退出。
  3. 使用非阻塞的connect套接字已建立連線,或者connect已經以失敗告終。即connect有結果了。
  4. 有一個錯誤的套接字待處理。對這樣的套接字的寫操作將不阻塞並返回-1(也就是返回了一個錯誤),同時把errno設定成確切的錯誤條件。這些待處理的錯誤也可以通過指定SO_ERROR套接字選項呼叫getsockopt獲取並清除。