1. 程式人生 > >TCP/IP詳解--TCP中異常關閉連線的意義 異常關閉的情況

TCP/IP詳解--TCP中異常關閉連線的意義 異常關閉的情況

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow

也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!

               

一、異常關閉連線的意義

    終止一個連線的正常方式是傳送FIN。在傳送緩衝區中所有排隊資料都已傳送之後才傳送FIN,正常情況下沒有任何資料丟失。

但我們有時也有可能傳送一個RST報文段而不是F

IN來中途關閉一個連線。這稱為異常關閉

    程序關閉socket的預設方式是正常關閉,如果需要異常關閉,利用SO_LINGER選項來控制。

     異常關閉一個連線對應用程式來說有兩個優點:

     (1)丟棄任何待發的已經無意義的資料,並立即傳送RST報文段;

     (2)RST的接收方利用關閉方式來區分另一端執行的是異常關閉還是正常關閉。

    值得注意的是RST報文段不會導致另一端產生任何響應,另一端根本不進行確認。收到RST的一方將終止該連線。程式行為如下:

    阻塞模型下,核心無法主動通知應用層出錯,只有應用層主動呼叫read()或者write()這樣的IO系統呼叫時,核心才會利用出錯來通知應用層對端RST。

非阻塞模型下,select或者epoll會返回sockfd可讀,應用層對其進行讀取時,read()會報錯RST。

haproxy的實現中用到了這個選項。

二、異常關閉連線的情況

遊戲測試過程中發現某些socket錯誤經常出現,以下是測試遊戲伺服器時通常考慮的case.
伺服器端:
1.
Case:客戶端程式正常執行的情況下,拔掉網線,殺掉客戶端程式
目的:模擬客戶端宕機、系統突然重啟、網線鬆動或網路不通等情況
結論:這種情況下伺服器程式沒有檢測到任何異常,並最後等待“超時”才斷開TCP連線

2.
Case:客戶端程式傳送很多資料包後正常關閉Socket並exit程序(或不退出程序)
目的:模擬客戶端傳送完訊息後正常退出的情況
結論:這種情況下伺服器程式能夠成功接收完所有訊息,並最後收到“對端關閉”(Recv返回零)訊息

3.
Case:客戶端程式傳送很多資料包後不關閉Socket直接exit程序
目的:模擬客戶端程式退出而忘記關閉Socket的情況(比如通過Windows視窗的關閉圖示退出程序,而沒有捕獲相應關閉事件做正常退出處理等)
結論:這種情況下伺服器程式能夠收到部分TCP訊息,然後收到“104: Connection reset by peer”(Linux下)或“10054: An existing connection was forcibly closed by the remote host”(Windows下)錯誤

4.
Case:客戶端程式傳送很多資料包的過程中直接Kill程序
目的:模擬客戶端程式崩潰或非正常方式結束程序(比如Linux下”kill -9″或Windows的工作管理員殺死程序)的情況
結論:這種情況下伺服器程式很快收到“104: Connection reset by peer”(Linux下)或“10054: An existing connection was forcibly closed by the remote host”(Windows下)錯誤

5.
Case:客戶端程式傳送很多資料包後正常關閉Socket並exit程序(或不退出程序)
目的:模擬客戶端正常關閉Socket後,伺服器端在檢查到TCP對端關閉前向客戶端傳送訊息的情況
結論:這種情況下伺服器程式接收和傳送部分TCP訊息後,在Send訊息時產生“32: Broken pipe”(Linux下)或“10053: An established connection was aborted by the software in your host machine”(Windows下)錯誤

總結:
當TCP連線的程序在忘記關閉Socket而退出、程式崩潰、或非正常方式結束程序的情況下(Windows客戶端),會導致TCP連線的對端程序產生“104: Connection reset by peer”(Linux下)或“10054: An existing connection was forcibly closed by the remote host”(Windows下)錯誤

當TCP連線的程序機器發生宕機、系統突然重啟、網線鬆動或網路不通等情況下,連線的對端程序可能檢測不到任何異常,並最後等待“超時”才斷開TCP連線

當TCP連線的程序正常關閉Socket時,對端程序在檢查到TCP關閉事件之前仍然向TCP傳送訊息,則在Send訊息時會產生“32: Broken pipe”(Linux下)或“10053: An established connection was aborted by the software in your host machine”(Windows下)錯誤

客戶端
1.
伺服器端已經close了Socket,客戶端再發送資料
目的:測試在TCP對端程序已經關閉Socket時,本端程序還未檢測到連線關閉的情況下繼續向對端傳送訊息
結論:第一包可以傳送成功,但第二包傳送失敗,錯誤碼為“10053: An established connection was aborted by the software in your host machine”(Windows下)或“32: Broken pipe,同時收到SIGPIPE訊號”(Linux下)錯誤

2.
伺服器端傳送資料到TCP後close了Socket,客戶端再發送一包資料,然後接收訊息
目的:測試在TCP對端程序傳送資料後關閉Socket,本端程序還未檢測到連線關閉的情況下發送一包訊息,並接著接收訊息
結論:客戶端能夠成功傳送第一包資料(這會導致伺服器端傳送一個RST包 <已抓包驗證>),客戶端再去Recv時,對於Windows和Linux程式有如下不同的表現:
Windows客戶端程式:Recv失敗,錯誤碼為“10053: An established connection was aborted by the software in your host machine”
Linux客戶端程式:能正常接收完所有訊息包,最後收到正常的對端關閉訊息(這一點與Window下不一樣)

3.
伺服器端在TCP的接收緩衝區中還有未接收資料的情況下close了Socket,客戶端再收包
目的:測試在TCP的接收緩衝區中還有未接收資料的情況下關閉Socket時,對端程序是否正常
結論:這種情況伺服器端就會向對端傳送RST包,而不是正常的FIN包(已經抓包證明),這就會導致客戶端提前(RST包比正常資料包先被收到)收到“10054: An existing connection was forcibly closed by the remote host”(Windows下)或“104: Connection reset by peer”(Linux下)錯誤

總結:
當TCP連線的對端程序已經關閉了Socket的情況下,本端程序再發送資料時,第一包可以傳送成功(但會導致對端傳送一個RST包過來):
之後如果再繼續傳送資料會失敗,錯誤碼為“10053: An established connection was aborted by the software in your host machine”(Windows下)或“32: Broken pipe,同時收到SIGPIPE訊號”(Linux下)錯誤;
之後如果接收資料,則Windows下會報10053的錯誤,而Linux下則收到正常關閉訊息

TCP連線的本端接收緩衝區中還有未接收資料的情況下close了Socket,則本端TCP會向對端傳送RST包,而不是正常的FIN包,這就會導致對端程序提前(RST包比正常資料包先被收到)收到“10054: An existing connection was forcibly closed by the remote host”(Windows下)或“104: Connection reset by peer”(Linux下)錯誤



           

給我老師的人工智慧教程打call!http://blog.csdn.net/jiangjunshow

這裡寫圖片描述