1 . 进程崩溃
Java
中的体现就是抛出异常,但没人 catch
,最终异常到了 JVM
这里,JVM
进程就会直接噶了。看起来是崩溃,挺严重,实际上操作系统会进行善后
- 当进程崩溃的时候,进程中的
PCB
就要被回收,PCB
中的文件描述符表里对应的所有文件也都会被系统自动关闭 - 其中针对
Socket
文件,也就会触发正常的关闭流程(TCP
四次挥手)
这样的情况看起来是异常,但实际上是一种正常情况,并不会有什么特殊处理,和正常关闭没有什么区别
2 . 主机关机(正常流程的关机)
正常流程点击关闭按钮的时候,此时操作系统就先干掉所有的进程(相当于第一种情况),在干的过程中,同样就会触发四次挥手
- 四次挥手非常快,四次挥手已经完成了,关机动作才完成
- 四次挥手没来得及挥完,关机就完成了
B 收到 FIN 后,就会立即返回一个 ACK,在紧接着 B 发送 FIN 的时候,就可能:
- A 已经关机完毕了,B 的 FIN 发过去之后,就不会有 ACK 了
- B 就会触发超时重传(B 只知道 A 要和他说拜拜,但并不知道 A 是要关机了)
- B 的超时重传会有上限,重传一定次数还没有响应,只能主动放弃连接(B 把保存的 A 的信息就删掉了)
3 . 主机掉电(直接拔电源)
1. 接收方掉电
- A 给 B 发送的数据,就不会再有
ACK
了 - A 触发超时重传,重传的数据当然还是没有响应
- 反复多次之后,A 尝试重置连接(
RST
) - 重置操作也没有
ACK
,A 就会单方面释放连接(A 把保存的 B 的信息删除掉)
TCP 正常断开,就是双方各自删除自己的(协议离婚)
TCP 异常断开,就是只能删除自己的,不管对面了(起诉离婚,强制执行)
2. 发送方掉电
A 发着发着没声了,在 B 的视角看来,不知道 A 是噶了,还是 A 只是稍微缓缓,晚点再发。此时 B 就会给 A 发送一个数据包,问问:“A 你怎么了”
- 这个包不携带业务数据,为了触发
ACK
- 若发了探测报文之后,A 返回了
ACK
,说明 A 只是先歇一会,没噶 - 若发了探测报文之后,A 没有 ACK,设置连续多个探测报文都没有
ACK
,就可以视为:A 已经噶了
就像在你打电话的时候,对面突然没声了,你就会:“喂?喂喂?喂喂喂?”问对方还在不在
这样的探测报文是周期性的,同时这个报文是用来探测对方“生死”的,也就把这样的报文称为“心跳包”
- 计算机中,非常广泛的使用“心跳包”的思想
- TCP 内置了心跳包,由于 TCP 内置的心跳包周期比较长,“秒级-分钟级”,应用程序这一层通常也会自行实现一些心跳包,达到更快速的“保活机制”
4 . 网线断开
和主机掉电是一样的,结合两种情况
- A 的视角:A 收不到 ACK,从而就会:
- 超时重传
- 重置连接
- 单方面释放
- B 的视角:
- A 突然没声了
- 心跳包也不通
- 重复多次心跳,判断对方不存在