TCP連線中的close和shutdown

2021-06-23 00:13:42 字數 1503 閱讀 4667

今天在看網路的書,自己想寫乙個tcp連線半關閉的程式.在連線建立之後,客戶端呼叫了close函式,但是伺服器端並沒有close.埠的狀態和書上講的一樣,客戶端進入過了fin_wait2狀態,而伺服器端進入了close_wait狀態.但是客戶端在繼續向客戶端寫入資料時,寫入成功,但是客戶端讀取出了錯誤.網上一查,發現時close函式呼叫的不對.

先說一下close和shutdown兩個函式的作用.

close函式首先將socket fd的reference減一,若reference依舊大於0,則該socket埠的狀態保持不變;若reference等於0,則首先將sender buffer中的資料全部傳送出去,並將receive buffer中的資料全部丟棄,最後傳送fin,執行主動關閉。這裡的關閉時將讀寫兩個方向的資料傳輸全部關閉,所以在呼叫close之後並不能從中讀取到資料.

而shutdown函式禁止了這個套接字的資料傳送,並且傳送傳送fin報文.特別說明的是:shutdown函式並不會去關閉fd,這個函式不會對fd進行操作

下面摘抄一下unix網路程式設計的敘述:

shutdown(shut_rd):在套介面上不能再發出接受請求;程序仍可往套介面傳送資料;套介面接受緩衝區中所有資料被丟棄;再接收到的資料被tcp丟棄,對套介面傳送緩衝區無影響.

shutdown(shut_wr)在套介面上不能在發出傳送請求;程序仍可以從套介面接受資料;套介面傳送緩衝區的內容被傳送到對端,後跟正常的tcp連線終止序列(傳送fin);對套介面接收緩衝區無任何影響.

close(l_onoff=0預設狀態):在套介面上不能在發出傳送或接收請求;套介面傳送緩衝區中的內容被傳送到對端.如果描述字引用計數變為0;在傳送完傳送緩衝區中的資料後,跟以正常的tcp連線終止序列(傳送fin);套介面接受緩衝區中內容被丟棄

close(l_onoff = 1, l_linger =0):在套介面上不能再發出傳送或接受請求,如果描述子引用計數變為0,rst被傳送到對端;連線的狀態被置為closed(沒有time_wait狀態),套介面傳送緩衝區和套介面接受緩衝區的資料被丟棄

close(l_onoff =1, l_linger != 0):在套介面上不能在發出傳送或接收請求;套介面傳送緩衝區中的內容被傳送到對端.如果描述字引用計數變為0;在傳送完傳送緩衝區中的資料後,跟以正常的tcp連線終止序列(傳送fin);套介面接受緩衝區中內容被丟棄;如果在連線變成closed狀態前延滯時間到,那麼close返回ewouldblock錯誤.

上面描述了何時只是關閉讀寫,何時要傳送fin報文終止連線,此外自己在寫**驗證的過程中,發現了乙個小問題

在使用close和shutdown函式時,客戶端狀態進入fin_wait2狀態,而伺服器端進入了close_wait狀態.但是當使用close函式時,超過一定的時間,客戶端會自動關閉套接字,而shutdown函式不會.上網查詢的原因時,這個是一般作業系統的實現,但是在tcp協議中沒有這個超時時間.設定超時的原因時,防止客戶端一直不釋放連線,當伺服器主動關閉時,不能**fd資源,導致伺服器崩潰.所以當使用close函式關閉套接字時,當狀態進入fin_wait2時,超過一定的時間,會自動關閉套接字.

tcp連線close過程

active passive tcp fin wait1 fin tcp fin wait2 ack tcp close wait data fin tcp last ack tcp time wait ack tcp close 2msl tcp close 其中 主動發起fin的一端的tcp t...

Android Http連線和TCP連線的區別

最近看到 裡提到某個架構選用tcp連線而不是http連線,意識到自己不知道這兩者的區別,遂查資料補一下知識。再用自己的話總結提煉一下 題目是android http連線和tcp連線的區別,因為我關注的使用場景是android環境,其實不管是android還是pc,應該都是一樣的。http是應用層協議...

qt中destroyed和close視窗有什麼區別

qt的assistant中關於destroyed只有qobject類的該訊號,其中說的很清楚 物件被destroyed前將立即傳送該訊號,其不能夠被阻塞。該物件的所有子物件在訊號傳送以後會被立即銷毀。而qwidget與qwindow差不多都是釋放視窗相關資源。qwidget的close槽函式是像wi...