如何才能正確的關閉Socket連線

2021-09-22 22:23:17 字數 1054 閱讀 9606

從tcp協議角度來看,乙個已建立的tcp連線有兩種關閉方式,一種是正常關閉,即四次揮手關閉連線;還有一種則是異常關閉,我們通常稱之為連線重置(reset)。

首先說一下正常關閉時四次揮手的狀態變遷,關閉連線的主動方狀態變遷是fin_wait_1->fin_wait_2->time_wait,而關閉連線的被動方的狀態變遷是close_wait->last_ack->time_wait。在四次揮手過程中ack包都是協議棧自動完成的,而fin包則必須由應用層通過closesocket或shutdown主動傳送,通常連線正常關閉後,recv會得到返回值0,send會得到錯誤碼10058。

除此之外,在我們的日常應用中,連線異常關閉的情況也很多。比如應用程式被強行關閉、本地網路突然中斷(禁用網絡卡、網線拔出)、程式處理不當等都會導致連線重置,連線重置時將會產生rst包,同時網路絡緩衝區中未接收(傳送)的資料都將丟失。連線重置後,本方send或recv會得到錯誤碼10053(closesocket時是10038),對方recv會得到錯誤碼10054,send則得到錯誤碼10053(closesocket時是10054)。

作業系統為我們提供了兩個函式來關閉乙個tcp連線,分別是closesocket和shutdown。通常情況下,closesocket會向對方傳送乙個fin包,但是也有例外。比如有乙個工作執行緒正在呼叫recv接收資料,此時外部呼叫closesocket,會導致連線重置,同時向對方傳送乙個rst包,這個rst包是由本方主動產生的。

shutdown可以用來關閉指定方向的連線,該函式接收兩個引數,乙個是套接字,另乙個是關閉的方向,可用值為sd_send,sd_receive和sd_both。方向取值為sd_send時,無論socket處於什麼狀態(recv阻塞,或空閒狀態),都會向對方傳送乙個fin包,注意這點與closesocket的區別。此時本方進入fin_wait_2狀態,對方進入close_wait狀態,本方依然可以呼叫recv接收資料;方向取值為sd_receive時,雙發連線狀態沒有改變,依然處於established狀態,本方依然可以send資料,但是,如果對方再呼叫send方法,連線會被立即重置,同時向對方傳送乙個rst包,這個rst包是被動產生的,這點注意與closesocket的區別。

如何正確的關閉socket linux

曾經遇到過好幾個問題,都是與客戶端或者服務端沒有完整關閉socket相關的。在 裡,隨處可見這類問題,只是隱藏較深,不容易暴露bug而已。乙個半關閉狀態的socket,其發起關閉的一方狀態是fin wait2,另一方是wait close 關於 遠端已經關閉連線,為何socket send 還是返回...

vue cli如何正確關閉prefetch

webpack4.6.0 新增了對prefetching和preloading的支援 通過在宣告匯入時使用內聯指令可以讓webpack輸出 resource hint 告訴瀏覽器 import webpackprefetch true loginmodal import webpackpreload...

關於socket通訊,如何才能高效?

他之前是做客戶端的,無奈人力資源緊張,也開始搞伺服器,他說自己的伺服器總是不穩定,於是就 聊到了這個話題,在他現有的專案中,大概有1000個鏈結,每個連線每秒發最大傳送四個資料報。而且 資料報的大小很小。伺服器在做壓力測試的時候,幾乎啥都沒有做,就是接到包,然後回覆,其他的 任務業務邏輯也沒有,連續...