WSAGetLastError可能會返回10053錯誤,查msdn的解釋是:
WSAECONNABORTED 10053
神馬?軟件原因造成的連接中斷,這是什么意思,不跟沒說一樣的么? Berkeley description: A connection abort was caused internal to your host machine. The software caused a connection abort because there is no space on the socket’s queue and the socket cannot receive further connections.
WinSock description: Partly the same as Berkeley. The error can occur when the local network system aborts a connection. This would occur if WinSock aborts an established connection after data retransmission fails (receiver never acknowledges data sent on a datastream socket).
TCP/IP scenario: A connection will timeout if the local system doesn’t receive an (ACK)nowledgement for data sent. It would also timeout if a (FIN)ish TCP packet is not ACK’d (and even if the FIN is ACK’d, it will eventually timeout if a FIN is not returned).
伯克利說這種連接中斷是因?yàn)樗拗鳈C(jī)器的內(nèi)部原因,因?yàn)檐浖?dǎo)致的連接中斷,可能是因?yàn)閟ocket的隊(duì)列滿并且這個socket不能接收更多的連接了。 The Scenario: Meanwhile, the client is still happily writing the remainder of the HTTP request to the socket. (Remember a TCP/IP socket connection needs to be closed from both sides. In this case, the server has closed its side, but the client is still pumping data into the half-open connection.) Go back and re-read the original error explanations. Hopefully, after that explanation, you’ll say "Aha! I understand what they’re talking about!".
啊哈,又有http了,大概意思就是http server收到請求了,但發(fā)現(xiàn)有問題,那么回一個http錯誤碼,然后就關(guān)閉了socket,但與此同時(shí),client端還在很開心地向socket寫數(shù)據(jù),注意哦,tcp是全雙工的。client寫完畢后,實(shí)際上數(shù)據(jù)只是放到了發(fā)送方的緩沖區(qū)中,不一定已經(jīng)發(fā)出去了,如果寫得不好的程序,這個時(shí)候就開始從socket讀數(shù)據(jù)了,這時(shí)候就會產(chǎn)生一個WSACONNECTABORTED錯誤,windows上對應(yīng)的就是10053錯誤。 但這個解釋實(shí)際上是不能讓人滿意的,只是舉出了一種場景,但為什么會產(chǎn)生還沒有解釋。后面又搜到了個參考2,首先解釋10053錯誤是收到fin后client會放棄發(fā)送緩沖區(qū)中的數(shù)據(jù),同時(shí)上報(bào)錯誤。雖然說法還有點(diǎn)一頭霧水。 不過這兩個參考給我們一個思路,重現(xiàn)這個問題。 于是簡單寫個測試用的c-s程序,大概流程如下
圖1 CS程序簡化流程圖 這個簡單程序演示如何出現(xiàn)10053錯誤(以及10054錯誤)。 如果server在收到client發(fā)送的數(shù)據(jù)后立即關(guān)閉socket,那么client再讀時(shí),會收到10053錯誤;如果server收到發(fā)送數(shù)據(jù)后,立即crash,那么隨后client再讀取時(shí)會收到10054錯誤。 ok,能夠重現(xiàn)場景了,那么我們來分析一下更細(xì)節(jié)的方面,網(wǎng)絡(luò)問題自然是抓包,本問題處理抓包還要看一下tcp的狀態(tài)以便輔助分析,我們在client端每次操作之前都打印當(dāng)前的tcp狀態(tài)。 下面是client端發(fā)送記錄和對應(yīng)的netstat情況
client在發(fā)送之前tcp狀態(tài)是established,在發(fā)送之后,server會立即關(guān)閉,tcp狀態(tài)也變?yōu)閏lose_wait,但這只是單方向的關(guān)閉,client可以繼續(xù)發(fā)數(shù)據(jù),但client發(fā)送后,server立即退出了,導(dǎo)致后續(xù)recv會失敗并且返回10053。對應(yīng)抓包情況如下: 圖3 10053錯誤client端tcp抓包 整個通信過程如下:
圖4 10054錯誤client端tcp狀態(tài)流轉(zhuǎn) 可以看到在crash之前這個tcp都是established狀態(tài)。crash之后,client端接收數(shù)據(jù)時(shí)會收到10054錯誤,場景重現(xiàn)了,我們再看一下抓包情況 圖5 10054錯誤client端tcp抓包 這個抓包情況跟10053很像,1-7也同10053,在8時(shí),client收到server發(fā)過來的reset,表示當(dāng)前連接被強(qiáng)制復(fù)位了。 7.回過頭來在看一開始的解釋,所謂軟件原因造成的連接終端,就是本例子中,server端在shoutdown本方向傳輸時(shí),立即關(guān)閉了socket,導(dǎo)致本應(yīng)該等待對方發(fā)送fin來完全結(jié)束的正常邏輯被打破,編程單方向強(qiáng)制中止本次tcp,導(dǎo)致client端之后向上報(bào)錯,就是所謂的10053錯誤了,這里的軟件就是server端的那個程序。(不過也有種說法是,客戶端發(fā)送錯誤數(shù)據(jù),導(dǎo)致server端保護(hù)機(jī)制而強(qiáng)制關(guān)閉)
| |
|