从TCP四次挥手理解java.io.IOException: Broken pipe异常现象

TCP正常四次挥手

四次挥手是指TCP连接的断开过程,它是建立再三次握手的基础之上。四次挥手过程用于正常关闭一个已经建立的TCP连接。

  1. 主动关闭方(通常是客户端)发送FIN(Finish):主动关闭方首先发送一个FIN报文段,表示它已经完成了数据的发送任务,并且希望关闭连接;发送FIN后,主动关闭方进入FIN-WAIT-1状态,等待被动关闭方的确认。
  2. 被动关闭方(通常是服务器)发送ACK:被动关闭方接收到主动关闭方的FIN后,会发送一个ACK(Acknowledgment)报文段,表示已经收到了关闭请求,并且进入CLOSE-WAIT状态(此时被动关闭方仍然可以发送未发生完毕的数据)。主动关闭方接收到报文进入FIN-WAIT-2状态。
  3. 被动关闭方发送FIN:被动关闭方在完成所有数据的发送后,会发送一个FIN报文给主动关闭方;被动关闭方进入LAST-ACK状态等待被动关闭方的确认。
  4. 主动关闭方发送ACK:主动关闭方收到被动关闭方的FIN后,会发送一个ACK报文段作为确认,表示已经收到了关闭请求;主动关闭方进入TIME-WAIT状态,等待可能出现的延迟的报文段(等待足够长的时间以确保被动关闭方收到了ACK报文段,防止出现任何延迟的报文段引发错误。完成TIME-WAIT状态后,TCP连接彻底关闭。)。

MSL(Maximum Segment Lifetime,最大报文段生存时间)

在这里插入图片描述

TCP三次握手

TCP三次握手是建立TCP连接的过程,用于确保客户端和服务器之间的通信可以进行。

  1. 客户端发送SYN报文段:客户端向服务器发送一个SYN(Synchronize Sequence Numbers同步序列编号)报文段,其中包含一个随机的初始序列号(seq=j),用于序列号的同步;发送SYN报文之后,客户端进入SYN-SENT(同步已发布)状态,等待服务器的确认。

  2. 服务器发送SYN-ACK报文段:服务器接收到客户端发送的SYN报文段后,向客户端发送一个SYN-ACK(同步-确认)报文段作为响应。SYN-ACK报文段中包含一个确认号,该确认号是客户端发送的序列化+1(ack=j+1)。服务器也会随机选择一个随机的初始序列号(seq=k)。发送SYN-ACK报文段之后,服务器进入SYN-RECEIVED(同步-收到)状态,等待客户端确认。

  3. 客户端发送ACK报文段:客户端收到服务器发送的SYN-ACK报文段后,会向服务器发送一个确认的ACK报文段。ACK报文段中包含一个确认号(ack=k+1),确认号是服务器发送的SYN报文段的序列号+1,同时客户端会选择一个随机的初始序列号(seq=z)。在发送ACK报文段后,客户端和服务器都进入ESTABLISHED状态,TCP连接建立完成。

在这里插入图片描述

状态

CLOSED

初始状态。

SYN_RCVD

这个状态表示接受到了SYN报文,在正常情况下,这个状态是服务器端的SOCKET在建立TCP连接时的三次握手会话过程中的一个中间状态,很短暂,基本上用netstat你是很难看到这种状态的,除非你特意写了一个客户端测试程序,故意将三次TCP握手过程中最后一个ACK报文不予发送。因此这种状态时,当收到客户端的ACK报文后,它会进入到ESTABLISHED状态。

SYN_SENT

客户端建立TCP连接发送第一个报文段后的状态。

ESTABLISHED

连接建立

FIN_WAIT_1

FIN_WAIT_1是SOCKET在ESTABLISHED状态发送FIN报文段之后的状态。
在实际的正常情况下,无论对方何种情况下,都应该马上回应ACK报文,所以FIN_WAIT_1状态一般是比较难见到的,而FIN_WAIT_2状态还有时常常可以用netstat看到。

CLOSE_WAIT

被关闭的SOCKET连接接收到一个FIN报文段,发送一个ACK报文段之后就进入这个状态。

FIN_WAIT_2

表示半连接,即有一方要close连接。
等待被关闭方的ACK报文后的状态,等待被关闭方的FIN报文段。

LAST_ACK

被动关闭一方在发送FIN报文后,最后等待对方的ACK报文状态。

TIME_WAIT

表示收到了对方的FIN报文,并发送出了ACK报文,就等2MSL后即可回到CLOSED可用状态了。如果FIN_WAIT_1状态下,收到了对方同时带FIN标志和ACK标志的报文时,可以直接进入到TIME_WAIT状态,而无须经过FIN_WAIT_2状态。

CLOSING

这种状态比较特殊,实际情况中应该是很少见,属于一种比较罕见的例外状态。正常情况下,当你发送FIN报文后,按理来说是应该先收到(或同时收到)对方的ACK报文,再收到对方的FIN报文。但是CLOSING状态表示你发送FIN报文后,并没有收到对方的ACK报文,反而却收到了对方的FIN报文。什么情况下会出现此种情况呢?其实细想一下,也不难得出结论:那就是如果双方几乎在同时close一个SOCKET的话,那么就出现了双方同时发送FIN报文的情况,也就会出现CLOSING状态,表示双方都正在关闭SOCKET连接。

触发Broken pipe方式

对于服务器来说,如果tcp连接已经建立,应该是会玩TCP的缓存通道中写入数据流,如果这个时候客户端强制终止了这个TCP连接,这个时候对于服务器操作系统层面来说,它可能是知道TCP的通道是要关闭的,但是其应该是不能之间通知到玩TCP通道中写入数据流的应用,如JavaWeb,这个时候可能就会出现java.io.IOException: Broken pipe异常。

方式一:客户端请求时间(超时)<服务端响应时间

方式二:服务端响应时间>网关最大响应时间

方式三:浏览器http请求响应为文件类型未开启自动下载

  • 20
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值