1. 10053
這個錯誤碼的意思是: A established connection was aborted by the software in your host machine, 一個已建立的連接所在主機的軟件中止
2. 10054
這個錯誤碼的意思是: Connection closed by peer, 連接已經被對方關閉
10053 出現的可能原因是:數據傳輸超時或者協議錯誤。
當主動端發起連接服務器的請求,連接成功之后發送數據請求給服務器,服務器處理時間稍長,導致客戶端超時關閉,等到服務器將數據寫入緩沖區后,TCP協議發現socket已經關閉,所以服務器會出現10053的錯誤碼,這是正常的現象。
10054 出現的可能原因是:對端關閉了socket(可能是異常也可能是超時),然而本端還沒有感知到,依舊寫入數據(對端接收緩沖區有數據),對端發現有未處理的數據直接回復RST重置連接標記,表明對端已經關閉了socket
檢測出這個錯誤碼一般是對端發送了RST包給本端,本端接收這個包, 表示對端出現了異常: 四種情況發送RST碼:
1. 本端連接對端未打開的端口, 對端發送RST包
2. 請求超時
3. 已關閉連接上收到數據:
主要出現在連接的關閉過程,當請求關閉連接的一方在兩個MSL后,仍然收到服務機發送來的最后一個FIN,說明其最后發送出的ACK丟包, 服務機又重發了FIN包,而此時客戶機已經不處於TIME_OUT狀態,連接已經徹底不存在,再收到服務機發送來的FIN,就會直接回復一個RST包,讓服務機直接關閉連接,拋棄 緩沖區的所有數據。
舉一個其他例子: 主動端關閉socket,發送了fin給被動端,此時主動端無法接受和發送數據了,此時如果被動端調用read會收到fin(讀取0),如果被動端write給主動端,主動端會發送rst,但rst不會立即通知到被動段,只有被動端在第二次write時,數據不會發送給主動端而是發出一個SIGPIPE信號而終止被動端(可捕獲忽略該信號)
4. close連接時, 接收緩沖區還有數據
如果close連接時,接收緩沖區還有對端發過來的數據,則回一個RST,直接丟棄接收緩沖區的內容
5. 設置了so_linger選項但是 l_lingertime 為0, close 時會發出RST
注意到10053和10054出現的原因有重復,以下是區分他倆的一個文章:
http://www.blogjava.net/pandawang/archive/2013/11/28/406922.html
某端出現10053和10054的在於主動端(客戶端)和被動端(服務器)建立連接后,服務器非正常關閉時有沒有關閉socket,這個fin包是不是在rst之前被客戶端收到,fin先於rst,則10053
update problem:
今天啟動flask的自帶server,非常簡單,就是一個直接返回字符串(有sleep操作,故意的),發送一個請求給flask,這個請求會超時: 1. 在本機上發,2. 在其他主機上發;
發現這倆種方法的結果不同,第一種會打印10053的錯誤信息,第二種不會;
經過microsoft message analyzer 抓包工具分析, 第一種操作,數據包是在環路接口流動,socket很快就關閉並回收了,導致server將響應返回時報錯,協議棧認為是自己關閉的所以報的10053,但其實應該是10054.
因為在一個已經關閉的socket寫會引起對端發送rst,連接重置,但因為是回路接口,windows的實現可能認為是自己關閉的,所以錯誤碼才是10053。
第二種因為不再同一個機器,對端關閉不影響,數據發送還是成功的(對端回復了rst),所以沒有報錯。
同樣的實驗在linux下面運行,報的錯是 error 32 broken pipe。這點和Windows不一樣,如果協議棧認為是自己關閉的,在linux上的錯誤應該是 error 53 ECONNABORTED。
所以數據傳輸的錯誤碼,在環路接口上可能與正常的理解不同,同時與系統相關。
以下附上抓包工具的結果:
下圖是client和server在統一機器上的情況:其報錯10053,看右側的第二個框,其響應並沒有寫入完全,就報錯,所以斷定是socket資源已經被銷毀了,但由於是在同一個機器,所以協議層認為是自己斷的,報了10053
ps:環路接口每個syn,fin,ack包都重發一遍了,不知道為啥。。。。
下圖是client和server不在同一機器上的情況:其未報10053, 可以看39938消息,數據是寫入緩沖區成功了,發送的時候對端回了rst,參考39950。 flask自帶的server可能處理了這種並沒有打印連接重置的錯誤
ps:
1. close 是優雅關閉過程,當socket的引用計數減少到0,開始優雅關閉流程,發送fin包,經四次握手關閉
2. shutdown 是直接破壞socket的通信,如果指定關閉WR,則發送fin包給對方