关于三次握手和四次挥手,面试官到底想听到怎样的回答?

news2024/11/20 8:42:54

我一看到 TCP,啪就点进来了,很快啊。

   TCP报文    

一个完整的 TCP 报文头部共有 20 个字节,其中包括:

  • 源端口号(16位)和目的端口号(16位):再加上 ip 首部的源 ip 地址和目的IP地址可以唯一确定一个 TCP 连接。

  • 数据序号(16位):表示在这个报文段中的第一个数据字节序号。

  • 确认序号:仅当ACK标志为 1 时有效,确认号表示期望收到的下一个字节的序号。

  • 偏移:就是头部长度,有 4 位,跟 ip 头部一样,以 4 字节为单位。最大是 60 个字节。

  • 保留位:6 位,必须为 0。

  • 6 个标志位:URG-紧急指针有效;ACK-确认序号有效;PSH-接收方应尽快将这个报文交给应用层;RST-连接重置;SYN-同步序号用来发起一个连接;FIN-终止一个连接。

  • 窗口字段:16 位,代表的是窗口的字节容量,也就是TCP的标准窗口最大为2^16 - 1 = 65535个字节。

  • 校验和:源机器基于数据内容计算一个数值,收信息机要与源机器数值结果完全一样,从而证明数据的有效性。检验和覆盖了整个的 TCP 报文段:这是一个强制性的字段,一定是由发送端计算和存储,并由接收端进行验证的。

图片

   TCP三次握手     

为了保证数据能到达目标,TCP 采用三次握手策略。

第一步:发送端首先会发送一个带有 SYN(synchronize)标志的数据包给接收方。第一次的 seq 序列号是随机产生的,这样是为了网络安全,如果不是随机产生初始序列号,黑客将会以很容易的方式获取到你与其他主机之间的初始化序列号,并且伪造序列号进行攻击。

第二步:接收端收到后,回传一个带有 SYN/ACK(acknowledgement)标志的数据包以示传达确认信息。SYN 是为了告诉发送端,发送方到接收方的通道没问题;ACK 用来验证接收方到发送方的通道没问题。

第三步:最后,发送端再回传一个带 ACK 标志的数据包,代表握手结束。若在握手某个过程中某个阶段莫名中断,TCP 协议会再次以相同的顺序发送相同的数据包。

Q:为什么要三次握手?

三次握手的目的是建立可靠的通信信道。说到通讯,简单来说就是数据的发送与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是正常的:

第一次握手,发送端:什么都确认不了;接收端:对方发送正常,自己接受正常。

第二次握手,发送端:对方发送,接受正常,自己发送,接受正常 ;接收端:对方发送正常,自己接受正常。

第三次握手,发送端:对方发送,接受正常,自己发送,接受正常;接收端:对方发送,接受正常,自己发送,接受正常。

Q:两次握手不行吗?为什么 TCP 客户端最后还要发送一次确认呢?

主要防止已经失效的连接请求报文突然又传送到了服务器,从而产生错误。经典场景:客户端发送了第一个请求连接并且没有丢失,只是因为在网络结点中滞留的时间太长了。

由于TCP的客户端迟迟没有收到确认报文,以为服务器没有收到,此时重新向服务器发送这条报文,此后客户端和服务器经过两次握手完成连接,传输数据,然后关闭连接。

此时此前滞留的那一次请求连接,网络通畅了到达服务器,这个报文本该是失效的,但是,两次握手的机制将会让客户端和服务器再次建立连接,这将导致不必要的错误和资源的浪费。

如果采用的是三次握手,就算是那一次失效的报文传送过来了,服务端接受到了那条失效报文并且回复了确认报文,但是客户端不会再次发出确认。由于服务器收不到确认,就知道客户端并没有请求连接。

Q:为什么三次握手,返回时 ack = seq + 1?

假设对方接收到数据,比如sequence number = 1000,TCP Payload = 1000,数据第一个字节编号为 1000,最后一个为 1999,回应一个确认报文,确认号为 2000,意味着编号 2000 前的字节接收完成,准备接收编号为 2000 及更多的数据。

确认收到的序列,并且告诉发送端下一次发送的序列号从哪里开始(便于接收方对数据排序,便于选择重传)。

Q:SYN 洪泛攻击(SYN Flood,半开放攻击),怎么解决?

什么是 SYN 洪范泛攻击?SYN Flood 利用 TCP 协议缺陷,发送大量伪造的 TCP 连接请求,常用假冒的IP或IP号段发来海量的请求连接的第一个握手包(SYN包),被攻击服务器回应第二个握手包(SYN+ACK包),因为对方是假冒 ip,对方永远收不到包且不会回应第三个握手包。导致被攻击服务器保持大量 SYN_RECV 状态的“半连接”,并且会重试默认 5 次回应第二个握手包,大量随机的恶意 syn 占满了未完成连接队列,导致正常合法的 syn 排不上队列,让正常的业务请求连接不进来。服务器端的资源分配是在二次握手时分配的,而客户端的资源是在完成三次握手时分配的,所以服务器容易受到 SYN 洪泛攻击。

检测 SYN 攻击非常的方便,当你在服务器上看到大量的半连接状态时,特别是源 ip 地址是随机的,基本上可以断定这是一次 SYN 攻击(在 Linux/Unix 上可以使用系统自带的 netstats 命令来检测 SYN 攻击)。

怎么解决?

  • 缩短超时(SYN Timeout)时间

  • 增加最大半连接数

  • 过滤网关防护

  • SYN cookies 技术

当服务器接受到 SYN 报文段时,不直接为该 TCP 分配资源,而只是打开一个半开的套接字。接着会使用 SYN 报文段的源 ip、目的 ip、端口号以及只有服务器自己知道的一个秘密函数生成一个 cookie,并把 cookie 作为序列号响应给客户端。

如果客户端是正常建立连接,将会返回一个确认字段为 cookie + 1 的报文段。接下来服务器会根据确认报文的源 ip、目的 ip、端口号以及秘密函数计算出一个结果,如果结果的值 + 1 等于确认字段的值,则证明是刚刚请求连接的客户端,这时候才为该 TCP 分配资源。

Q:TCP三次握手中,最后一次回复丢失,会发生什么?

如果最后一次 ACK 在网络中丢失,那么 server 端(服务端)该 TCP 连接的状态仍为 SYN_RECV,并且根据 TCP 的超时重传机制依次等待 3 秒、6 秒、12 秒后重新发送 SYN+ACK 包,以便 client(客户端)重新发送 ACK 包.

如果重发指定次数后,仍然未收到 ACK 应答,那么一段时间后,server(服务端)自动关闭这个连接.

但是 client(客户端)认为这个连接已经建立,如果 client(客户端)端向 server(服务端)发送数据,server 端(服务端)将以 RST 包(Reset,标示复位,用于异常的关闭连接)响应,此时,客户端知道第三次握手失败。

   TCP四次挥手     

主动断开方(客户端/服务端)- 发送一个 FIN,用来关闭主动断开方(客户端/服务端)到被动断开方(客户端/服务端)的数据传送。

被动断开方(客户端/服务端)- 收到这个 FIN,它发回一 个 ACK,确认序号为收到的序号加1 。和 SYN 一样,一个 FIN 将占用一个序号。

被动点开方(客户端/服务端)- 关闭与主动断开方(客户端/服务端)的连接,发送一个FIN给主动断开方(客户端/服务端)。

主动断开方(客户端/服务端)- 发回 ACK 报文确认,并将确认序号设置为收到序号加1。

Q:为什么连接的时候是三次握手,关闭的时候却是四次握手?

建立连接的时候, 服务器在 listen 状态下,收到建立连接请求的 SYN 报文后,把 ACK 和 SYN 放在一个报文里发送给客户端。

关闭连接时,服务器收到对方的 FIN 报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以服务器可以立即关闭,也可以发送一些数据给对方后,再发送 FIN 报文给对方来表示同意现在关闭连接。因此,服务器 ACK 和 FIN 一般都会分开发送,从而导致多了一次。

Q:为什么TCP挥手每两次中间有一个 FIN-WAIT2等待时间?

主动关闭的一端调用完 close 以后(即发FIN给被动关闭的一端, 并且收到其对 FIN 的确认 ACK )则进入 FIN_WAIT_2 状态。如果这个时候因为网络突然断掉、被动关闭的一段宕机等原因,导致主动关闭的一端不能收到被动关闭的一端发来的FIN(防止对端不发送关闭连接的FIN包给本端),这个时候就需要 FIN_WAIT_2 定时器, 如果在该定时器超时的时候,还是没收到被动关闭一端发来的 FIN,那么直接释放这个链接,进入 close 状态。

Q:为什么客户端最后还要等待 2MSL?为什么还有个 TIME-WAIT 的时间等待?

保证客户端发送的最后一个 ACK 报文能够到达服务器,因为这个 ACK 报文可能丢失,服务器已经发送了 FIN+ACK 报文,请求断开,客户端却没有回应,于是服务器又会重新发送一次,而客户端就能在这个 2MSL 时间段内收到这个重传的报文,接着给出回应报文,并且会重启 2MSL 计时器。

防止类似与“三次握手”中提到了的“已经失效的连接请求报文段”出现在本连接中。客户端发送完最后一个确认报文后,在这个2MSL时间中,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,这样新的连接中不会出现旧连接的请求报文。

2MSL,最大报文生存时间,一个 MSL 30 秒,2MSL = 60s。

Q:客户端 TIME-WAIT 状态过多会产生什么后果?怎样处理?

作为服务器,短时间内关闭了大量的 client 连接,就会造成服务器上出现大量的 TIME_WAIT 连接,占据大量的 tuple/tApl/ ,严重消耗着服务器的资源,此时部分客户端就会显示连接不上。

作为客户端,短时间内大量的短连接,会大量消耗的 client 机器的端口,毕竟端口只有 65535 个,端口被耗尽了,后续就无法在发起新的连接了。

在高并发短连接的 TCP 服务器上,当服务器处理完请求后立刻主动正常关闭连接。这个场景下会出现大量 socket 处于 TIME_WAIT 状态。如果客户端的并发量持续很高,此时部分客户端就会显示连接不上:

  • 高并发可以让服务器在短时间范围内同时占用大量端口,而端口有个 0~65535 的范围,并不是很多,刨除系统和其他服务要用的,剩下的就更少了。

  • 短连接表示“业务处理+传输数据的时间 远远小于 TIMEWAIT 超时的时间”的连接。

解决方法:

  • 用负载均衡来抗这些高并发的短请求。

  • 服务器可以设置 SO_REUSEADDR 套接字选项来避免 TIME_WAIT状态,TIME_WAIT 状态可以通过优化服务器参数得到解决,因为发生TIME_WAIT的情况是服务器自己可控的,要么就是对方连接的异常,要么就是自己没有迅速回收资源,总之不是由于自己程序错误导致的。

  • 强制关闭,发送 RST 包越过 TIMEWAIT 状态,直接进入 CLOSED 状态。

Q:服务器出现了大量 CLOSE_WAIT 状态如何解决?

大量 CLOSE_WAIT 表示程序出现了问题,对方的 socket 已经关闭连接,而我方忙于读或写没有及时关闭连接,需要检查代码,特别是释放资源的代码,或者是处理请求的线程配置。

Q:服务端会有一个 TIME_WAIT 状态吗?如果是服务端主动断开连接呢?

发起链接的主动方基本都是客户端,但是断开连接的主动方服务器和客户端都可以充当,也就是说,只要是主动断开连接的,就会有 TIME_WAIT 状态。

四次挥手是指断开一个 TCP 连接时,需要客户端和服务端总共发送 4 个包以确认连接的断开。在 socket 编程中,这一过程由客户端或服务端任一方执行 close 来触发。

由于 TCP 连接是全双工的,因此,每个方向的数据传输通道都必须要单独进行关闭。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/851615.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

canvas实现代码雨

学习抖音&#xff1a; 渡一前端必修课 效果图&#xff1a; 全部代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge">&…

实现 Notification 通知

如图这种效果 可以使用 Notification API来进行实现 代码如下 注意&#xff1a;一定要用服务端打开。不然不会弹出来。vscode可以安装 live Serve 插件服务端打开 <!DOCTYPE html> <html lang"zh"><head><meta charset"UTF-8">…

git-指令

1.名称和邮箱 git config --global user.name test git config --global user.email testatguigu.com 这里的--global表示全局配置&#xff0c;后续的所有文件操作都会使用该用户名称及邮箱。此时在操作系统的用户目录C:\Users\Administrator&#xff0c;会产生新的配置文件.gi…

【Python】基础:标准库常用模块

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍标准库常用模块。 学其所用&#xff0c;用其所学。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下次更新不迷路&#…

什么是Milvus

原文出处&#xff1a;https://www.yii666.com/blog/393941.html 什么是Milvus Milvus 是一款云原生向量数据库&#xff0c;它具备高可用、高性能、易拓展的特点&#xff0c;用于海量向量数据的实时召回。 Milvus 基于 FAISS、Annoy、HNSW 等向量搜索库构建&#xff0c;核心是…

开发工具Eclipse的使用

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于Eclipse使用的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.Eclipse是什么 二.使用Eclipse的…

OLED透明屏选购指南:性能、品牌与预算的平衡

引言&#xff1a;OLED透明屏作为一种创新的显示技术&#xff0c;正在迅速发展并广泛应用于各个领域。 然而&#xff0c;面对市场上琳琅满目的OLED透明屏产品&#xff0c;如何选择适合自己需求的高品质产品成为了采购者们的重要任务。 对此&#xff0c;尼伽将为您提供一份OLED…

webshell链接工具-Behinder(冰蝎)

“冰蝎”动态二进制加密网站管理客户端 项目地址&#xff1a; https://github.com/rebeyond/Behinder

大模型“瘦身”进手机 下一个iPhone时刻将至?

一股“端侧大模型”浪潮正在涌来。华为、高通等芯片巨头正探索将AI大模型植入端侧&#xff0c;让手机实现新一代物种进化。 相比ChatGPT、Midjourney等AI应用依赖云端服务器提供服务&#xff0c;端侧大模型主打在本地实现智能化。它的优势在于能够更好地保护隐私&#xff0c;同…

以太网UDP协议(十一)

目录 一、端口号 二、UDP 一、端口号 端口号&#xff0c;用来识别同一台计算机中进行通信的不同应用程序&#xff0c;也别成为程序地址。 备注&#xff1a;端口号由其使用的传输层协议决定。因此&#xff0c;不同的传输协议可以使用相同的端口号。即TCP和UDP可以同时使用相同…

php实现登录的例子

界面&#xff1a; 登录界面login.html代码&#xff1a; <!DOCUMENT html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns"http://www.w3.org/1999/xhtml"…

css的transform样式计算-第一节

本文作者为 360 奇舞团前端开发工程师 引言 在使用 css 样式进行样式的缩放、旋转等设置时&#xff0c;思考了一下它的较浅层的原理&#xff0c;恩&#xff0c;这个阶段都 是一些初高的数学计算&#xff0c;从新看这里的时候顺便捡了捡初高中的数学&#xff0c;比如三角函数之类…

重生之我要学C++第七天(匿名对象、内部类)

构造函数的隐式类型转化 1.单参数构造函数隐式类型转换 来看下面的代码 #include<iostream> using namespace std; class A { public:A(int x){_a x;} private:int _a; }; int main() {A a 3;return 0; } 此处这句代码 A a 3; 对于这里&#xff0c;编译完全正确&…

【Java从0到1学习】07 Java异常

尽管人人希望自己身体健康&#xff0c;处理的事情都能顺利进行&#xff0c;但在实际生活中总会遇到各种状况&#xff0c;比如感冒发烧&#xff0c;工作时电脑蓝屏、死机等。同样&#xff0c;在程序运行的过程中&#xff0c;也会发生各种非正常状况&#xff0c;比如程序运行时磁…

工作区与GOPATH

在学习go语言时&#xff0c;我们会从官网下载go语言的二进制包&#xff0c;然后解压并安装到某个目录&#xff0c;最后会配置环境变量&#xff0c;通过输入命令go version来验证是否安装成功。 配置了path环境后&#xff0c;我们还需要再配置3个环境变量&#xff0c;GOROOT、G…

Stable Diffusion - 哥特 (Goth) 风格服装与背景的 LoRA 配置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132177882 图像来源于 Goth Clothing 的 LoRA 效果&#xff0c;配合哥特 (Goth) 风格服饰的相关提示词。 测试模型&#xff1a;DreamShaper 8 哥…

websocket+node实现直播(弱鸡版)

心血历程 这部分主要是写在写这些的时候遇到的问题以及换思路的过程&#xff0c;可以之间看正文 在之前我也写过直播功能&#xff0c;并且与websocket相结合实现了直播弹幕。只不过直播是使用的腾讯云的&#xff0c;而不是手写的直播推流拉流&#xff0c;这次又有一个新的项目…

百川智能发布首个530亿参数闭源大模型,今年追上GPT-3.5

4月官宣创业&#xff0c;6月15日发布第一款7B开源模型&#xff0c;7月11日发布第二款13B、130亿参数开源模型。 平均保持2个月一个版本发布速度&#xff0c;8月8日&#xff0c;百川智能发布了创业以来的首个530亿参数闭源大模型——Baichuan-53B&#xff08;以下简称“53B”&a…

运维作业5

一.基于 CS 7 构建 LVS-DR 群集。 1.lvs安装ipvsadm [rootnode ~]# yum install -y ipvsadm 2.配置lvs虚拟ip&#xff08;vip&#xff09; [rootnode ~]# ifconfig ens32:200 192.168.72.200 netmask 255.255.255.0 up 客户端测试&#xff1a; 3.在两台rs上安装httpd 4.两台rs建…

SpringBoot3之Web编程

标签&#xff1a;Rest.拦截器.swagger.测试; 一、简介 基于web包的依赖&#xff0c;SpringBoot可以快速启动一个web容器&#xff0c;简化项目的开发&#xff1b; 在web开发中又涉及如下几个功能点&#xff1a; 拦截器&#xff1a;可以让接口被访问之前&#xff0c;将请求拦截…