网络面试-0x11 TCP为什么需要三次握手和四次挥手?

2023-10-22 05:30

本文主要是介绍网络面试-0x11 TCP为什么需要三次握手和四次挥手?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

网络面试-0x11 TCP为什么需要三次握手和四次挥手?

alt

一、三次握手

三次握手[three-way-handshake]:客户端和服务器总共发送3个包,以建立TCP连接。

什么是连接了?主要作用是什么?

连接:
主要作用:为了确认双方的接收能力发送能力是否正常,指定自己的初始化序列号为后面的可靠性传送做准备。

alt 过程如下:
1)第一次握手:客户端发送搞一个SYN报文给服务端,并且报文中指明了客户端的初始化系列seq=ISN(c),此时,客户端处于SYN_SENT状态
2)第二次握手:服务器收到客户端的SYN包,处理之后,发送自己的SYN+ACK包,将客户端的ISN+1作为ack的值,此时,服务器处于SYN_RCVD的状态。
3)第三次握手:客户端发送一个ACK报文,seq=ISN+1。此时客户端处于ESTABLISHED状态。 服务器收到ACK报文之后,也处于ESTABLISHED状态,此时,双方已建立起了连接。

每次握手的作用:

第一次握手:客户端的发送能力、服务器的接收能力是正常的。
第二次握手:服务器的接收、发送能力正常,客户端的接收、发送能力是正常的。 不过,此时服务器并不能确认客户端的接收能力是否正常。
第三次握手:客户端接收、发送能力正常,服务器自己的发送、接收能力也正常。

1、为什么不是两次握手?

如果两次握手,发送端能够确定自己发送的信息对方能够收到,而对方发送的消息,发送端也能够收到。 接收端只能够确定对方发送的消息自己能够收到,而无法确定自己发送的消息对方能够收到。

2、第2次握手传回了ACK,为什么要穿SYN?

ACK 是告诉客户端发来的数据已经接受无误,而传回SYN是为了把自己的初始化序列号seq同步给客户端。

二、 四次挥手

TCP 终止一个连接, 需要经过四次发包的过程。

alt 挥手过程:
1)第一次挥手:客户端发送一个FIN报文,报文中指定一个序列号。 此时,客户端处于FIN_WAIT1状态, 停止发送数据,等待服务端的确认。seq=x
2)第二次挥手:服务端接收到FIN报文之后,发送ACK报文, ack=x+1, seq=Y, 此时,服务端处于CLOSE_ WAIT状态。
3)第三次挥手:如果服务端也想断开连接, 和客户端的第一次挥手是一样的,发送FIN报文, 指定一个序列号, 此时,服务器处于LAST_ACK的状态。
4)第四次挥手:客户端收到FIN之后,一样发送一个ACK报文作为应答,且把服务器的序列号值+1作为自己ACK报文的序号值,此时客户端处于TIME_WAIT状态。需要过一阵子以确保服务端收到自己的ACK报文之后才会进入CLOSED状态,服务端收到ACK报文之后,就处于关闭比连接了,处于CLOSED状态。

1、 四次挥手原因

服务端在收到客户端断开连接FIN报文后,并不会立即关闭连接, 而是先发送一个ACK包线告诉客户端收到关闭连接的请求,只有当服务器的所有报文发送完毕之后,才发送FIN报文断开连接,因此需要四次挥手。

2、CLOSE-WAIT 和 TIME-WAIT 的状态和意义

CLOSE-WAIT: 服务器收到客户端关闭连接的请求并告诉客户端自己已经成功收到了请求之后, 服务器进入CLOSE-WAIT状态,然而此时有可能服务端还有一些数据没有传输完成,因此不能立即关闭连接, 而CLOSE-WAIT状态就是为了保证服务器在关闭连接之前将待发送的数据发送完成。

TIME-WAIT:发生在第四次挥手,当客户端收到那个服务端发送ACK确认报文后进入该状态,若取消该状态,即客户端在收到服务端的FIN报文后立即关闭连接,此时,
(1)服务端相应的端口并没有关闭,若客户端在相同的端口立即建立了新的连接,则有可能接收到上次连接残留的数据包,可能会导致不可以预料的异常出现。—— 保证没有收到残余的数据
(2)除此之外,假设客户端最后一次发送的ACK包在传输时候丢失,由于TCP协议的超时重传机制,服务端将重发FIN报文,若客户端并没有维持TIME-WAIT状态而直接关闭的话,当收到服务端重新发送的FIN包时,客户端就会用RST包来响应服务端,这就会使得对方认为是有错误发生,然而其实只是正常的关闭连接过程,并没有出现异常情况。 —— 保证最后一个ACK到达

3、TIME-WAIT 状态会导致什么问题?怎么解决?

场景: 高并发业务
在高并发短连接的TCP服务器上,当服务器处理完请求后,主动请求关闭连接,这样服务器上会有大量的连接处于TIME_WAIT状态,服务器维护每个连接需要一个socket,也就是每个连接会占用一个文件描述符,而文件描述符的使用有上限的,如果持续高并发,会导致一些正常的连接失败。
解决方案:修改配置或设置SO_REUSEADDR套接字,使得服务器处于TIME-WAIT状态下的端口能够快速回收和重用。

4、TIME-WAIT为什么是2MSL?

当客户端发出最后的ACK确认报文时,并不能够确定服务器端能够接收到该段报文。 所以,此时会设置一个2MSL的计时器。2MSL即是服务器端发出FIN报文和客户端发出的ACK确认报文所能保持有效的最大时长。
若是服务器没有收到ACK报文,再次向客户端发送FIN报文。 如果客户端在2MSL内收到了服务器再次发来的FIN报文,说明服务器由于一些原因并没有收到客户端发出的ACK确认报文。客户端将再次向服务器发出ACK确认报文,并重新开始2MSL计时。 所以:客户端要经历2MSL市场的TIME-WAIT阶段,为的是确认服务器能否接收到客户端发出的ACK确认报文。

区分 MSL, TTL, RTT

1、MSL(Maximum Segment Lifetime) 报文最大生存空间,任何报文在网络上存在的最长时间,超过这个时间报文将被丢弃,因为TCP报文(segment)是IP数据报(datagram)的数据部分。 每个具体的TCP实现都必须选择一个确定的MSL值。RFC 1122建议是2分钟。
2、TTL(time to live)生存时间。ip头中有一个TTL域,这个生存时间是由源主机设置初始值但并不是存的具体时间,而是存储的一个IP数据报可以经过的最大路由数,每经过一个处理他的路由器此值就-1,当此值位0则数据报将被丢弃,同时发送ICMP报文通知源主机。RFC 793中规定MSL为2分钟,实际应用中常用的是30秒,1分钟和2分钟等。
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。
3、RTT(round-trip time) 客户端到服务器往返所花的时间。TCP含有动态估算RTT的算法。TCP还持续估算一个给定连接的RTT,这是因为RTT受网络传输拥塞程序的变化而变化。
表示从发送端发送数据开始,到发送端收到来自接收端的确认(接收端收到数据后便立即发送确认),总共经历的时延。
一般认为单向时延=传输时延t1+传播时延t2+排队时延t3
t1是数据从进入节点到传输媒体所需要的时间,通常等于数据块长度/信道带宽
t2是信号在信道中需要传播一定距离而花费的时间,等于信道长度/传播速率(光纤中电磁波的传播速率约为210^5 km/s,铜缆中2.310^5 km/s)
t3可笼统归纳为随机噪声,由途径的每一跳设备及收发两端负荷情况及吞吐排队情况决定(包含互联网设备和传输设备时延)

5、有很多TIME-WAIT状态如何解决?

服务器可以设置SO_REUSEADDR套接字选项来通知内核,如果端口被占用,但 TCP 连接位于 TIME_WAIT 状态时可以重用端口。如果你的服务器程序停止后想立即重启,而新的套接字依旧希望使用同一端口,此时 SO_REUSEADDR 选项就可以避免 TIME-WAIT 状态。
也可以采用长连接的方式减少 TCP 的连接与断开,在长连接的业务中往往不需要考虑 TIME-WAIT 状态,但其实在长连接的业务中并发量一般不会太高。

6、有很多CLOSE-WAIT状态如何解决?

1)检查是不是自己的代码问题(看是否服务端程序忘记关闭连接),如果是,则修改代码 2)调整系统参数,包括句柄相关的参数和TCP/IP的参数,一般一个CLOSE_WAIT会维持至少2个小时的时间,我们可以通过调整参数来缩短这个时间。

常见的关键缩写:

CWR: 拥塞窗口减(发送方降低它的发送速率) ECE: ECN会显(发送方接收到一个更早的拥塞通告) URG: 紧急(紧急指针字段有效 —— 很少被使用) ACK: 确认(确认号字段有效 —— 连接建立以后,一般都启用状态) PSH:推送(接收方应尽快给应用程序传送这个数据 —— 没被可靠地实现或用到) RST:重置连接(连接取消,经常是因为错误) SYN:用于初始化一个连接的同步序号 FIN:该报文端发送方已经结束向对方发送数据。

三、 总结

alt

公众号:`技术小难`
[简书](https://www.jianshu.com/u/1851ec413025)
[博客园](https://account.cnblogs.com/blog-apply) 链接需要替换
[CSDN](https://blog.csdn.net/u012496940?spm=1000.2115.3001.5343)
[知乎](https://www.zhihu.com/people/gu-han-90-61)
[掘金](https://juejin.cn/user/1943592286824333)
[segmentfault](https://segmentfault.com/u/natqeeak/articles)

本文由 mdnice 多平台发布

这篇关于网络面试-0x11 TCP为什么需要三次握手和四次挥手?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/259340

相关文章

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

SpringBoot使用OkHttp完成高效网络请求详解

《SpringBoot使用OkHttp完成高效网络请求详解》OkHttp是一个高效的HTTP客户端,支持同步和异步请求,且具备自动处理cookie、缓存和连接池等高级功能,下面我们来看看SpringB... 目录一、OkHttp 简介二、在 Spring Boot 中集成 OkHttp三、封装 OkHttp

Linux系统之主机网络配置方式

《Linux系统之主机网络配置方式》:本文主要介绍Linux系统之主机网络配置方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、查看主机的网络参数1、查看主机名2、查看IP地址3、查看网关4、查看DNS二、配置网卡1、修改网卡配置文件2、nmcli工具【通用

使用Python高效获取网络数据的操作指南

《使用Python高效获取网络数据的操作指南》网络爬虫是一种自动化程序,用于访问和提取网站上的数据,Python是进行网络爬虫开发的理想语言,拥有丰富的库和工具,使得编写和维护爬虫变得简单高效,本文将... 目录网络爬虫的基本概念常用库介绍安装库Requests和BeautifulSoup爬虫开发发送请求解

Java8需要知道的4个函数式接口简单教程

《Java8需要知道的4个函数式接口简单教程》:本文主要介绍Java8中引入的函数式接口,包括Consumer、Supplier、Predicate和Function,以及它们的用法和特点,文中... 目录什么是函数是接口?Consumer接口定义核心特点注意事项常见用法1.基本用法2.结合andThen链

如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解

《如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别详解》:本文主要介绍如何通过海康威视设备网络SDK进行Java二次开发摄像头车牌识别的相关资料,描述了如何使用海康威视设备网络SD... 目录前言开发流程问题和解决方案dll库加载不到的问题老旧版本sdk不兼容的问题关键实现流程总结前言作为

SSID究竟是什么? WiFi网络名称及工作方式解析

《SSID究竟是什么?WiFi网络名称及工作方式解析》SID可以看作是无线网络的名称,类似于有线网络中的网络名称或者路由器的名称,在无线网络中,设备通过SSID来识别和连接到特定的无线网络... 当提到 Wi-Fi 网络时,就避不开「SSID」这个术语。简单来说,SSID 就是 Wi-Fi 网络的名称。比如

Java实现任务管理器性能网络监控数据的方法详解

《Java实现任务管理器性能网络监控数据的方法详解》在现代操作系统中,任务管理器是一个非常重要的工具,用于监控和管理计算机的运行状态,包括CPU使用率、内存占用等,对于开发者和系统管理员来说,了解这些... 目录引言一、背景知识二、准备工作1. Maven依赖2. Gradle依赖三、代码实现四、代码详解五

QT实现TCP客户端自动连接

《QT实现TCP客户端自动连接》这篇文章主要为大家详细介绍了QT中一个TCP客户端自动连接的测试模型,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录版本 1:没有取消按钮 测试效果测试代码版本 2:有取消按钮测试效果测试代码版本 1:没有取消按钮 测试效果缺陷:无法手动停