TCP中幾種RST的情況
在TCP協議中RST表示復位,用來異常的關閉連線,在TCP的設計中它是不可或缺的。傳送RST包關閉連線時,不必等緩衝區的包都發出去,直接就丟棄快取區的包傳送RST包。而接收端收到RST包後,也不必傳送ACK包來確認。
在網路程式設計過程中,各種RST錯誤比較難排查和找到原因,基於此,根據以往的經驗以及找到的一些資料,整理了以下幾種RST的情況。
埠未開啟
伺服器程式埠未開啟而客戶端來連線。這種情況是最為常見和好理解的一種了。去telnet一個未開啟的TCP的埠可能會出現這種錯誤。這個和作業系統的實現有關。在某些情況下,作業系統也會完全不理會這些發到未開啟埠請求。
當然在某些作業系統的主機上,未必是這樣的表現。比如向一臺WINDOWS7的主機發送一個連線不存在的埠的請求,這臺主機就不會迴應。
請求超時
曾經遇到過這樣一個情況:一個客戶端連線伺服器,connect返回-1並且error=EINPROGRESS。 直接telnet發現網路連線沒有問題。ping沒有出現丟包。用抓包工具檢視,客戶端是在收到伺服器發出的SYN之後就莫名其妙的傳送了RST。
有89、27兩臺主機。主機89向主機27傳送了一個SYN,表示希望連線8888埠,主機27迴應了主機89一個SYN表示可以連線。但是主機27卻很不友好,莫名其妙的傳送了一個RST表示我不想連線你了。
後來經過排查發現,在主機89上的程式在建立了socket之後,用setsockopt的SO_RCVTIMEO選項設定了recv的超時時間為100ms。而我們看上面的抓包結果表示,從主機89發出SYN到接收SYN的時間多達110ms。(從15:01:27.799961到15:01:27.961886, 小數點之後的單位是微秒)。因此主機89上的程式認為接收超時,所以傳送了RST拒絕進一步傳送資料。
提前關閉
關於TCP,我想我們在教科書裡都讀到過一句話,’TCP是一種可靠的連線’。 而這可靠有這樣一種含義,那就是作業系統接收到的來自TCP連線中的每一個位元組,我都會讓應用程式接收到。如果應用程式不接收怎麼辦?你猜對了,RST。
在一個已關閉的socket上收到資料
如果某個socket已經關閉,但依然收到資料也會產生RST。