首页 > 其他分享 >TCP三次握手和四次挥手

TCP三次握手和四次挥手

时间:2023-04-16 21:32:29浏览次数:42  
标签:握手 报文 TCP 四次 WAIT FIN 连接 服务端 客户端


文章目录

  • TCP三次握手
  • TCP四次挥手

TCP三次握手

TCP三次握手和四次挥手_tcp/ip


序列号:建立连接时计算机随机生成的随机数作为初始值,通过SYN包传给接收端主机,每发送一次数据就累加一次该数据字节数的大小。用来解决网络包乱序问题

确认应答号:指下一次期望收到的数据的序列号,发送端收到这个确认应答以后认为在这个序号以前的数据都已经被正常接受。用来解决丢包问题

ACK:确认应答的字段变为有效,TCP规定除了最初建立的SYN包外该位必须设置为1

RST:表示TCP连接中出现异常必须强制断开连接

SYN:表示希望建立连接,并在其序列号的字段进行序列号初始值的设定

FIN:表示今后不会再有数据发送,希望断开连接。通信结束希望断开连接时,通信双方的主机之间就可以相互交换FIN位为1的TCP段。使用TCP前必须先建立连接,建立连接是通过三次握手来进行的。

TCP三次握手和四次挥手_网络_02


三次握手中,第三次握手是可以携带数据的,前两次握手是不可以携带数据的。一旦完成三次握手,双方都处于ESTABLISHED状态,此时连接就已建立完成,客户端和服务端就可以相互发送数据了。

Linux系统查看TCP状态

netstat -napt

TCP三次握手和四次挥手_tcp/ip_03

TCP四次挥手

TCP三次握手和四次挥手_客户端_04


客户端打算关闭连接,此时会发送一个 TCP 首部 FIN 标志位被置为 1 的报文,也即 FIN 报文,之后客户端进入 FIN_WAIT_1 状态。

服务端收到该报文后,就向客户端发送 ACK 应答报文,接着服务端进入 CLOSE_WAIT 状态。

客户端收到服务端的 ACK 应答报文后,之后进入 ==FIN_WAIT_2 ==状态。

等待服务端处理完数据后,也向客户端发送 FIN 报文,之后服务端进入 LAST_ACK 状态。

客户端收到服务端的 FIN 报文后,回一个 ACK 应答报文,之后进入 TIME_WAIT 状态

服务端收到了 ACK 应答报文后,就进入了 CLOSE 状态,至此服务端已经完成连接的关闭。

客户端在经过 2MSL 一段时间后,自动进入 CLOSE 状态,至此客户端也完成连接的关闭。为什么挥手需要四次?

关闭连接时,客户端向服务端发送 FIN 时,仅仅表示客户端不再发送数据了但是还能接收数据。

服务端收到客户端的 FIN 报文时,先回一个 ACK 应答报文,而服务端可能还有数据需要处理和发送(closed_wait),等服务端不再发送数据时,才发送 FIN 报文给客户端来表示同意现在关闭连接。

服务端通常需要等待完成数据的发送和处理,所以服务端的 ACK 和 FIN 一般都会分开发送,因此是需要四次挥手。

第一次挥手丢失,会发生什么?

根据 tcp_orphan_retries 决定重传次数

TCP三次握手和四次挥手_tcp/ip_05

第二次挥手丢失,会发生什么?

由于ACK不会重传,如果服务端第二次挥手丢失客户端就会触发超时重传机制,重传FIN报文

根据 tcp_orphan_retries 决定重传次数

TCP三次握手和四次挥手_linux_06


注意:

对于 close 函数关闭的连接,由于无法再发送和接收数据,所以FIN_WAIT2 状态不可以持续太久,而 tcp_fin_timeout 控制了这个状态下连接的持续时长,默认值是 60 秒。

如果主动关闭方使用 shutdown 函数关闭连接,指定了只关闭发送方向,而接收方向并没有关闭,那么意味着主动关闭方还是可以接收数据的,就会死等对方的FIN。

TCP三次握手和四次挥手_linux_07

第三次挥手丢失,会发生什么?

同理第一次挥手丢失

TCP三次握手和四次挥手_服务端_08

第四次挥手丢失,会发生什么?

在 Linux 系统,TIME_WAIT 状态会持续 2MSL 后才会进入关闭状态。

客户端在收到第三次挥手后,就会进入 TIME_WAIT 状态,开启时长为 2MSL 的定时器,如果途中再次收到第三次挥手(FIN 报文)后,就会重置定时器,当等待 2MSL 时长后,客户端就会断开连接。

TCP三次握手和四次挥手_客户端_09


为什么 TIME_WAIT 等待的时间是 2MSL?

MSL为报文最大生存时间(单位是时间)TTL是经过路由跳数,因此MSL应该大于等于TTL消耗为0的时间确保报文已被自然消亡。

当这些发送方的数据包被接收方处理后又会向对方发送响应,所以一来一回需要等待 2 倍的时间
至少运行报文丢失一次
连续两次丢包概率万分之一,概率太小,忽略它比解决它更有性价比

2MSL 的时间是从客户端接收到 FIN 后发送 ACK 开始计时的。如果在 TIME-WAIT 时间内,因为客户端的 ACK 没有传输到服务端,客户端又接收到了服务端重发的 FIN 报文,那么 2MSL 时间将重新计时。

为什么需要TIME_WAIT状态?
主动发起关闭连接的一方才会有TIME_WAIT。
两个原因:

  • 防止历史连接的数据被后面相同四元组的连接错误的接收
  • 保证被关闭连接的一方,能被正确的关闭
    原因一:
    序列号和初始化序列号并不是无限递增的,会发生回绕为初始值的情况,这意味着无法根据序列号来判断新老数据。
    假设TIME_WAIT没有等待时间或时间过短,被延迟的数据包抵达后会发生什么?

    相当于重新打开新连接,前面被延迟的SEQ=301抵达客户端,而且这个报文的序列号刚好在客户端接收窗口内,因此客户端会正常接收这个数据报文,但这个数据报文是上一个连接残留下来的,这样就产生数据错乱等严重的问题。
    因此为了防止历史连接中的数据被后面相同四元组的连接错误的接收,TCO设计了TIME_WAIT状态,状态会持续2MSL时长,这个时间足以让两个方向上的数据包都被丢弃,使得原来连接的数据包在网络中自然消失,再出现的数据包一定都是新建立连接所产生的

原因二:
等待足够的时间来确保最后的ACK能让被动关闭方接收,从而帮助其正常关闭。

TCP三次握手和四次挥手_网络_10


服务端收到这个 RST 并将其解释为一个错误(Connection reset by peer),这对于一个可靠的协议来说不是一个优雅的终止方式。

为防止这种情况,客户端等足够长时间确保服务端能够收到ACK,如果服务端没有收到ACK就会触发TCP重传机制,服务端会重新发生一个FIN,这样一去一来刚好两个MSL时间。

客户端在收到服务端重传的 FIN 报文时,TIME_WAIT 状态的等待时间,会重置回 2MSL。

TCP三次握手和四次挥手_网络_11


TIME_WAIT 过多有什么危害?

占用系统资源,占用端口资源。

注意一个四元组唯一确定一个TCP连接。

服务器出现大量的TIME_WAIT状态原因有哪些?

如果服务器出现大量的 TIME_WAIT 状态的 TCP 连接,就是说明服务器主动断开了很多 TCP 连接。

服务端主动断开连接的场景:

  • HTTP没有使用长连接
  • HTTP长连接超时
  • HTTP长连接请求数量达到上限

场景一:根据大多数 Web 服务的实现,不管哪一方禁用了 HTTP Keep-Alive,都是由服务端主动关闭连接,那么此时服务端上就会出现 TIME_WAIT 状态的连接。

当服务端出现大量的 TIME_WAIT 状态连接的时候,可以排查下是否客户端和服务端都开启了 HTTP Keep-Alive,因为任意一方没有开启 HTTP Keep-Alive,都会导致服务端在处理完一个 HTTP 请求后,就主动关闭连接,此时服务端上就会出现大量的 TIME_WAIT 状态的连接。

场景二:为了避免资源浪费的情况,web 服务软件一般都会提供一个参数,用来指定 HTTP 长连接的超时时间,比如 nginx 提供的 keepalive_timeout 参数。假设设置了 HTTP 长连接的超时时间是 60 秒,nginx 就会启动一个「定时器」,如果客户端在完后一个 HTTP 请求后,在 60 秒内都没有再发起新的请求,定时器的时间一到,nginx 就会触发回调函数来关闭该连接,那么此时服务端上就会出现 TIME_WAIT 状态的连接。

TCP三次握手和四次挥手_网络_12


如果现象是有大量的客户端建立完 TCP 连接后,很长一段时间没有发送数据,那么大概率就是因为 HTTP 长连接超时,导致服务端主动关闭连接,产生大量处于 TIME_WAIT 状态的连接。可以往网络问题的方向排查,比如是否是因为网络问题,导致客户端发送的数据一直没有被服务端接收到,以至于 HTTP 长连接超时

场景三:

nginx 的 keepalive_requests 这个参数,这个参数是指一个 HTTP 长连接建立之后,nginx 就会为这个连接设置一个计数器,记录这个 HTTP 长连接上已经接收并处理的客户端请求的数量如果达到这个参数设置的最大值时,则 nginx 会主动关闭这个长连接,那么此时服务端上就会出现 TIME_WAIT 状态的连接。

对于一些 QPS 比较高的场景,比如超过 10000 QPS,甚至达到 30000 , 50000 甚至更高,如果 keepalive_requests 参数值是 100,这时候就 nginx 就会很频繁地关闭连接,那么此时服务端上就会出大量的 TIME_WAIT 状态。针对这个场景下,解决的方式也很简单,调大 nginx 的 keepalive_requests 参数就行

服务器出现大量 CLOSE_WAIT 状态的原因有哪些?
CLOSE_WAIT 状态是「被动关闭方」才会有的状态,而且如果「被动关闭方」没有调用 close 函数关闭连接,那么就无法发出 FIN 报文,从而无法使得 CLOSE_WAIT 状态的连接转变为 LAST_ACK 状态。所以,当服务端出现大量 CLOSE_WAIT 状态的连接的时候,说明服务端的程序没有调用 close 函数关闭连接
如果已经建立了连接,但是客户端突然出现故障了怎么办?
客户端出现故障指的是客户端的主机发生了宕机,或者断电的场景。发生这种情况的时候,如果服务端一直不会发送数据给客户端,那么服务端是永远无法感知到客户端宕机这个事件的,也就是服务端的 TCP 连接将一直处于ESTABLISH状态,占用着系统资源。
TCP有一个保活机制:
定义一个时间段,在这个时间段内,如果没有任何连接相关的活动,TCP 保活机制会开始作用,每隔一个时间间隔,发送一个探测报文,该探测报文包含的数据非常少,如果连续几个探测报文都没有得到响应,则认为当前的 TCP 连接已经死亡,系统内核将错误信息通知给上层应用程序。
如果已经建立了连接,但是服务端的进程崩溃会发生什么?
TCP连接信息由内核维护,当服务端的进程崩溃后,内核需要回收进程所有TCP连接资源,于是内核会发送第一次挥手FIN报文,后续的挥手过程也都是内核完成,无需进程参与,因此即使服务端进程退出,还是能与客户端完成TCP四次挥手操作。


标签:握手,报文,TCP,四次,WAIT,FIN,连接,服务端,客户端
From: https://blog.51cto.com/u_15911055/6193587

相关文章

  • TCP为什么可靠,采用了什么方法
    首先对比IP层,IP层不可靠,不保证网络包的交付,不保证网络包的按序交付,也不保证网络包的数据完整性。而TCP在传输层进行可靠的数据传输服务,接受到的网络包无损坏,无间隔,非冗余按序。TCP无论网络链路出现了怎样的链路变化,TCP都可以保证一个报文一定能够到达接收端。通过TCP连接保证可......
  • TCP为什么要三次握手,而不是两次或四次?
    文章目录TCP为什么要三次握手,而不是两次或四次?三次握手才可以阻止重复历史连接的初始化(主要原因)同步双方初始序列号避免资源浪费小结TCP为什么要三次握手,而不是两次或四次?TCP连接时用于保证可靠性和流量控制维护的某些状态信息,这些信息的组合,包括Socket,序列号和窗口大小称为连接。......
  • IP层会分片,为什么TCP层还需要MSS?
    MTU:一个网络包的最大长度,以太网一般为1500字节MSS:除去IP和TCP头部之后,一个网络包所能容纳的TCP数据的最大长度如果一个IP分片丢失,整个IP报文的所有分片都得重传。IP层进行分片传输没有效率:IP层没有超时重传机制,由传输层的TCP来负责超时和重传,当某个IP分片丢失后,接收方的IP层无法......
  • 为什么每次建立TCP连接时初始化的序列号都要求不一样
    为了防止历史报文被下一个相同的四元组的连接接受假设每次建立连接。客户端和服务端的初始化序列号都是从0开始的客户端和服务端建立了一个TCP连接,在客户端发送数据包被网络阻塞了然后超时重传了这个数据包,而此时服务端断电重启,之前与客户端建立的连接也消失了,于是收到客户端的数......
  • LYT-C#-Socket——简单的TCP服务端-客户端连接通信
    https://learn.microsoft.com/zh-cn/dotnet/api/system.net.sockets.tcplistener?view=netframework-4.8.1TCP编程的服务器端一般步骤是:1、创建一个socket,用函数socket()。2、设置socket属性。3、绑定本机的IP地址、端口等信息到socket上,用函数bind()。......
  • Centos 服务器放行TCP、UDP端口教程
     在运行CentOS操作系统时,经常需要放行某个端口,以便应用程序能够正常运行。今天飞飞将和你分享centos服务器放行tcp、udp端口教程,希望可以帮助到您~ 首先用SSH连接工具连接服务器,如果你不知道如何连接Linux服务器,可以参考下这篇教程 比如我们在安装宝塔后面板无法访问,提......
  • socket与TCP的关系
    Socket是一种抽象封装,等价于应用程序和网络中间的一层,以便在应用程序和操作系统内核之间传输数据。TCP是一个可靠的、面向连接的协议,用于在计算机之间传输数据。Socket可以用于创建TCP连接,在应用程序间传输数据,它们是紧密相关的,其中Socket提供了创建、绑定、监听、接受、连接、发......
  • tcp性能优化方法
    一、TCPfastopen原理简介:三次握手带来的延迟使得每创建一个新TCP连接都要付出很大代价。而这也决定了提高TCP应用性能的关键,在于想办法重用连接。TFO(TCPfastopen)允许服务器和客户端在连接建立握手阶段交换数据,从而使应用节省了一个RTT的时延。但是TFO会引起一些问题,因此......
  • 计算机网络 传输层协议TCP和UDP
    目录一、传输层协议二、tcp协议介绍三、tcp报文格式四、tcp三次握手五、tcp四次挥手六、udp协议介绍七、常见协议和端口八、有限状态机  一、传输层协议传输层协议主要是TCP和UDP协议主要作用1.分段和重组2.会话多路复用 二、tcp协议......
  • Python 实现tcp/ip协议&&CAN通信
    七层链路模型(Seven-LayerOSIModel)物数网传会表应--物理层、数据链路层、网络层、传输层、会话层、表示层(负责数据格式的转换和加密解密操作)和应用层。TCP/IP协议的四个层:应用层:应用层是TCP/IP协议中最高层,主要定义了各种应用程序的协议和数据格式。常见的应用层协议包括......