在socket通信過程中蔼水,經(jīng)常發(fā)現(xiàn)客戶端或者服務(wù)器的日志中出現(xiàn)“broken pipe”或者“connection reset by peer”的錯(cuò)誤提示。
以前一直以為自己理解了這兩個(gè)錯(cuò)誤異常提示所包含的意義儒飒,而實(shí)際理解完全錯(cuò)誤舵盈。
我的錯(cuò)誤理解和下面這段來自blogspot的表述差不多:
```
Maybe I'm just dumb, but I always thought "broken pipe" meant, "the other end of this socket closed before I finished sending something" and "connection reset by peer" meant, well, roughly the same thing. (As well as indicating some slightly more esoteric problems.)
Turns out though, "broken pipe" actually means "I just tried to send something and the socket was already closed to sending."
So in the following example, if the other end of (TCP) socket "sock" closes or dies before the write method, "connection reset by peer" will be raised. The next write will give a broken-pipe error, since the socket now knows that further sending is invalid.
```
```
try:
? ? sock.write('foo')
except:
? ? pass # connection reset by peer
sock.write('bar') # broken pipe
```
reset報(bào)文發(fā)送場(chǎng)景
RST的標(biāo)志位论矾,這個(gè)標(biāo)識(shí)為在如下幾種情況下會(huì)被設(shè)置,以下是我了解的情況沛简,可能還有更多的場(chǎng)景齐鲤,沒有驗(yàn)證:
1. 當(dāng)嘗試和未開放的服務(wù)器端口建立tcp連接時(shí),服務(wù)器tcp將會(huì)直接向客戶端發(fā)送reset報(bào)文
2. 雙方之前已經(jīng)正常建立了通信通道椒楣,也可能進(jìn)行過了交互给郊,當(dāng)某一方在交互的過程中發(fā)生了異常,如崩潰等捧灰,異常的一方會(huì)向?qū)Χ税l(fā)送reset報(bào)文淆九,通知對(duì)方將連接關(guān)閉
3. 當(dāng)收到TCP報(bào)文统锤,但是發(fā)現(xiàn)該報(bào)文不是已建立的TCP連接列表可處理的,則其直接向?qū)Χ税l(fā)送reset報(bào)文
4. ack報(bào)文丟失炭庙,并且超出一定的重傳次數(shù)或時(shí)間后饲窿,會(huì)主動(dòng)向?qū)Χ税l(fā)送reset報(bào)文釋放該TCP連接
其實(shí)我們java異常里看到的Broken pipe或者Connection reset by peer信息不是jdk或者jvm里定義的,我看到這些關(guān)鍵字往往會(huì)首先搜索下jdk或者h(yuǎn)otspot源碼找到位置進(jìn)行上下文分析焕蹄,但是沒找到逾雄,后面才想到應(yīng)該是Linux或者glibc里定義的,果然在glibc里看到了如上的描述和定義腻脏。
對(duì)于Broken pipe在管道的另外一端沒有進(jìn)程在讀的時(shí)候就會(huì)拋出此異常鸦泳,Connection reset by peer的描述其實(shí)不是很正確,從我的實(shí)踐來看只描述了一方面永品,其實(shí)在某一端正常close之后做鹰,也是可能會(huì)有此異常的。
connection reset by peer”和”broken pipe”出現(xiàn)的場(chǎng)景:
1)往一個(gè)對(duì)端已經(jīng)close的通道寫數(shù)據(jù)的時(shí)候鼎姐,對(duì)方的tcp會(huì)收到這個(gè)報(bào)文钾麸,并且反饋一個(gè)reset報(bào)文。當(dāng)收到reset報(bào)文的時(shí)候症见,繼續(xù)做select讀數(shù)據(jù)的時(shí)候就會(huì)拋出Connect reset by peer的異常喂走,。
2)當(dāng)?shù)谝淮瓮粋€(gè)對(duì)端已經(jīng)close的通道寫數(shù)據(jù)的時(shí)候會(huì)和上面的情況一樣谋作,會(huì)收到reset報(bào)文。當(dāng)再次往這個(gè)socket寫數(shù)據(jù)的時(shí)候乎芳,就會(huì)拋出Broken pipe了 遵蚜。根據(jù)tcp的約定,當(dāng)收到reset包的時(shí)候奈惑,上層必須要做出處理吭净,調(diào)用將socket文件描述符進(jìn)行關(guān)閉,其實(shí)也意味著pipe會(huì)關(guān)閉肴甸,因此會(huì)拋出這個(gè)顧名思義的異常寂殉。
參考
從tcp原理角度理解Broken pipe和Connection Reset by Peer的區(qū)別
http://lovestblog.cn/blog/2014/05/20/tcp-broken-pipe
關(guān)于tcp socket出現(xiàn)的”connection reset by peer“和“broken pipe”
http://mdba.cn/2015/04/07/%E5%85%B3%E4%BA%8Etcp-socket%E5%87%BA%E7%8E%B0%E7%9A%84connection-reset-by-peer%E5%92%8Cbroken-pipe