socket可讀,可寫的條件


socket可讀可寫條件,經常做爲面試題被問,因爲它考察被面試者對網絡編程的基礎瞭解的是不是夠深入。要了解socket可讀可寫條件,我們先了解幾個概念:
1.接收緩存區低水位標記(用於讀)和發送緩存區低水位標記(用於寫):

每個套接字有一個接收低水位和一個發送低水位。他們由select函數使用。

接收低水位標記是讓select返回"可讀"時套接字接收緩衝區中所需的數據量。對於TCP,其默認值爲1。

發送低水位標記是讓select返回"可寫"時套接字發送緩衝區中所需的可用空間。對於TCP,其默認值常爲2048.


通俗的解釋一下,緩存區我們當成一個大小爲 n bytes的空間,那麼:

接收區緩存的作用就是,接收對面的數據放在緩存區,供應用程序讀。當然了,只有當緩存區可讀的數據量(接收低水位標記)到達一定程度(eg:1)的時候,我們才能讀到數據,不然不就讀不到數據了嗎。
發送區緩存的作用就是,發送應用程序的數據到緩存區,然後一起發給對面。當然了,只有當緩存區剩餘一定空間(發送低水位標記)(eg:2048),你才能寫數據進去,不然可能導致空間不夠。

2.FIN: (結束標誌,Finish)用來結束一個TCP回話.但對應端口仍處於開放狀態,準備接收後續數據.



首先來看看socket可讀的條件.


一、下列四個條件中的任何一個滿足時,socket準備好讀: 
1. socket的接收緩衝區中的數據字節大於等於該socket的接收緩衝區低水位標記的當前大小。對這樣的socket的讀操作將不阻塞並返回一個大於0的值(也就是返回準備好讀入的數據)。我們可以用SO_RCVLOWATsocket選項來設置該socket的低水位標記。對於TCP和UDP .socket而言,其缺省值爲1.
2. 該連接的讀這一半關閉(也就是接收了FIN的TCP連接)。對這樣的socket的讀操作將不阻塞並返回0
3.socket是一個用於監聽的socket,並且已經完成的連接數爲非0.這樣的soocket處於可讀狀態,是因爲socket收到了對方的connect請求,執行了三次握手的第一步:對方發送SYN請求過來,使監聽socket處於可讀狀態;正常情況下,這樣的socket上的accept操作不會阻塞;
4.有一個socket有異常錯誤條件待處理.對於這樣的socket的讀操作將不會阻塞,並且返回一個錯誤(-1),errno則設置成明確的錯誤條件.這些待處理的錯誤也可通過指定socket選項SO_ERROR調用getsockopt來取得並清除;


再來看看socket可寫的條件.


二、下列三個條件中的任何一個滿足時,socket準備好寫: 

1. socket的發送緩衝區中的數據字節大於等於該socket的發送緩衝區低水位標記的當前大小。對這樣的socket的寫操作將不阻塞並返回一個大於0的值(也就是返回準備好寫入的數據)。我們可以用SO_SNDLOWAT socket選項來設置該socket的低水位標記。對於TCP和UDPsocket而言,其缺省值爲2048

2. 該連接的寫這一半關閉。對這樣的socket的寫操作將產生SIGPIPE信號,該信號的缺省行爲是終止進程。

3.有一個socket異常錯誤條件待處理.對於這樣的socket的寫操作將不會阻塞並且返回一個錯誤(-1),errno則設置成明確的錯誤條件.這些待處理的錯誤也可以通過指定socket選項SO_ERROR調用getsockopt函數來取得並清除;


解釋一下連接的讀/寫這一半關閉:


如圖:

終止一個連接需要4個分節,主動關閉的一端(A)調用close發送FIN到另一端(B),B接收到FIN後,知道A已經主動關閉了,也就是,A不會發數據來了,那麼這一端調用read必然可讀,且返回0(read returns 0).

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章