如何理解 TCP 四次挥手

简介: 【4月更文挑战第11天】TCP关闭连接需四次挥手:一方发送FIN包进入FIN_WAIT_1,对方收到后进入CLOSE_WAIT,读取EOF并发送FIN,进入LAST_ACK;另一方收到FIN并ACK,进入TIME_WAIT,等待2MSL后关闭。每个方向的FIN和ACK各一次,故称四次挥手。UDP不需建立连接,断开时删除目的地址和端口映射。

TCP 建立一个连接需 3 次握手,而终止一个连接则需要四次挥手。四次挥手的整个过程是这样的:

image.png

首先,一方应用程序调用 close,我们称该方为主动关闭方,该端的 TCP 发送一个 FIN 包,表示需要关闭连接。之后主动关闭方进入 FIN_WAIT_1 状态。


接着,接收到这个 FIN 包的对端执行被动关闭。这个 FIN 由 TCP 协议栈处理,我们知道,TCP 协议栈为 FIN 包插入一个文件结束符 EOF 到接收缓冲区中,应用程序可以通过 read 调用来感知这个 FIN 包。一定要注意,这个 EOF 会被放在已排队等候的其他已接收的数据之后,这就意味着接收端应用程序需要处理这种异常情况,因为 EOF 表示在该连接上再无额外数据到达。此时,被动关闭方进入 CLOSE_WAIT 状态。


接下来,被动关闭方将读到这个 EOF,于是,应用程序也调用 close 关闭它的套接字,这导致它的 TCP 也发送一个 FIN 包。这样,被动关闭方将进入 LAST_ACK 状态。

最终,主动关闭方接收到对方的 FIN 包,并确认这个 FIN 包。主动关闭方进入 TIME_WAIT 状态,而接收到 ACK 的被动关闭方则进入 CLOSED 状态。经过 2MSL 时间之后,主动关闭方也进入 CLOSED 状态。


每个方向都需要一个 FIN 和一个 ACK,因此通常被称为四次挥手。


当套接字被关闭时,TCP 为其所在端发送一个 FIN 包。在大多数情况下,这是由应用进程调用 close 而发生的,值得注意的是,一个进程无论是正常退出(exit 或者 main 函数返回),还是非正常退出(比如,收到 SIGKILL 信号关闭,就是我们常常干的 kill -9),所有该进程打开的描述符都会被系统关闭,这也导致 TCP 描述符对应的连接上发出一个 FIN 包。


MSL 是任何 IP 数据报能够在因特网中存活的最长时间。其实它的实现不是靠计时器来完成的,在每个数据报里都包含有一个被称为 TTL(time to live)的 8 位字段,它的最大值为 255。TTL 可译为“生存时间”,这个生存时间由源主机设置初始值,它表示的是一个 IP 数据报可以经过的最大跳跃数,每经过一个路由器,就相当于经过了一跳,它的值就减 1,当此值减为 0 时,则所在的路由器会将其丢弃,同时发送 ICMP 报文通知源主机。RFC793 中规定 MSL 的时间为 2 分钟,Linux 实际设置为 30 秒。


2MSL即两倍的MSL,TCP的TIME_WAIT状态也称为2MSL等待状态,当TCP的一端发起主动关闭,在发出最后一个ACK包后,即第3次握手完成后发送了第四次握手的ACK包后就进入了TIME_WAIT状态,必须在此状态上停留两倍的MSL时间。


等待2MSL时间主要目的是怕最后一个ACK包对方没收到,那么对方在超时后将重发第三次握手的FIN包,主动关闭端接到重发的FIN包后可以再发一个ACK应答包。 在TIME_WAIT状态时两端的端口不能使用,要等到2MSL时间结束才可继续使用。


当连接处于2MSL等待阶段时任何迟到的报文段都将被丢弃。不过在实际应用中可以通过设置SO_REUSEADDR选项达到不必等待2MSL时间结束再使用此端口。


TTL与MSL是有关系的但不是简单的相等的关系,MSL要大于等于TTL。


UDP 连接套接字不是发起连接请求的过程,而是记录目的地址和端口到套接字的映射关系。断开套接字则相反,将删除原来记录的映射关系。


我们知道,对于 TCP 套接字,connect 只能调用一次。但是,对一个 UDP 套接字来说,进行多次 connect 操作是被允许的,这样主要有两个作用。第一个作用是可以重新指定新的 IP 地址和端口号;第二个作用是可以断开一个已连接的套接字。为了断开一个已连接的 UDP 套接字,第二次调用 connect 时,调用方需要把套接字地址结构的地址族成员设置为 AF_UNSPEC。


相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
30天前
|
网络协议 程序员
为什么TCP需要三次握手?一文讲透!
TCP三次握手是TCP协议建立连接的关键步骤,确保客户端和服务端同步状态并确认彼此的存在。过程分为三步:1) 客户端发送SYN包请求连接;2) 服务端回应SYN/ACK包确认收到并提供初始序列号;3) 客户端发送ACK包确认服务端的序列号,双方进入连接状态。此机制确保了双向通信的可靠性和资源的有效利用,避免了失效请求导致的问题。
|
4月前
|
网络协议 算法 Linux
深度解密 TCP 三次握手与四次挥手
深度解密 TCP 三次握手与四次挥手
86 9
|
网络协议
八股文-TCP的三次握手
TCP协议是一种面向连接、可靠传输的协议,而建立连接的过程就是著名的三次握手。这个过程保证了通信的双方能够同步信息,确保后续的数据传输是可靠和有序的。本文将深入解析TCP三次握手的步骤及其意义。
93 1
|
8月前
|
网络协议 Linux 存储
深入理解Linux网络——TCP连接建立过程(三次握手源码详解)
一、相关实际问题 1. 为什么服务端程序都需要先listen一下 2. 半连接队列和全连接队列长度如何确定 3. “Cannot assign requested address”这个报错是怎么回事 4. 一个客户端端口可以同时用在两条连接上吗 5. 服务端半/全连接队列满了会怎么样 6. 新连接的soket内核对象是什么时候建立的 7. 建立一条TCP连接需要消耗多长时间 8. 服务器负载很正常,但是CPU被打到底了时怎么回事
|
网络协议 安全 Linux
TCP 三次握手与四次挥手深入探究(大图解)
TCP 三次握手与四次挥手深入探究(大图解)
671 1
|
缓存 网络协议
图解TCP的三次握手和四次挥手
图解TCP的三次握手和四次挥手
101 0
|
网络协议 Linux 应用服务中间件
粗略探讨一下tcp四次挥手
粗略探讨一下tcp四次挥手
361 0
|
缓存 网络协议 安全
TCP三次握手四次挥手及常见问题解决方案
TCP三次握手四次挥手及常见问题解决方案
TCP三次握手四次挥手及常见问题解决方案
|
网络协议 前端开发
前端面试题( TCP 三次握手和四次挥手的理解)
前端面试题( TCP 三次握手和四次挥手的理解)
134 0
前端面试题( TCP 三次握手和四次挥手的理解)