【计算机网络】TCP协议——2.连接管理(三次握手,四次挥手)

目录

前言 

一. 建立连接——三次握手

1. 三次握手过程描述

2. TCP连接建立相关问题

二. 释放连接——四次挥手

1. 四次挥手过程描述

2. TCP连接释放相关问题

三. TCP状态转换

结束语


前言 

TCP——传输控制协议(Transmission Control Protocol)。是一种面向连接的传输层通信协议

什么是连接

TCP连接是指通过TCP协议在网络中建立的一种可靠的通信链路。TCP连接在应用层之间提供可靠,高效的通信方式,广泛应用于互联网上的各种应用,如网页浏览,电子邮件,文件传输等。

建立连接在操作系统中是需要有对应的数据结构管理,维护的。所以连接的建立,维护都是有成本的

为什么要建立连接

  1. 更好的保证可靠性:建立连接的过程其实就是让通信双方验证各自的发送能力和接收能力是否正常,当前发送接收两端信道是否通畅。
  2. 协商一些重要参数,如:序号初始值,MSS,是否启用SACK,等等。

MSS和SACK可参看【计算机网络】TCP协议报头详解的选项部分

TCP建立连接,通信,断开连接的流程总图如下:

一. 建立连接——三次握手

1. 三次握手过程描述

1. 服务器初始化状态

服务器端进程先创建传输控制块(TCB),socket()创建套接字listenfd,bind()将套接字和端口号绑定,服务器进程准备接收客户端的连接请求。然后服务器进程调用listen()函数,使listenfd成为监听套接字,后续连接都从监听套接字获取。此时服务器端进程处于监听(listen)状态,紧接着调用accept()函数,在listenfd套接字中等待客户的连接到来

服务器端进程调用函数顺序:socket => bind => listen => accept。当执行到accept函数时,服务器进程会一直处于阻塞状态,直到有客户连接请求到达才返回

 【2. 客户端发起连接请求,发送SYN同步报文段,第一次握手

客户端进程也创建传输控制块(TCB),socket()创建套接字,然后向服务器端发送连接请求报文段,这时请求报文段的首部标志位SYN=1,同时选择一个初始序号seq=x,这个初始序号x是随机产生的整数ISN。TCP规定,SYN报文段(即SYN=1的TCP报文段)不能携带数据,但要消耗一个序号。此时,客户端进程进入SYN-SENT(同步报文已发送)状态

客户端进程函数调用顺序:socket => connect。当客户端调用connect函数时,操作系统会自动bind(),客户端进程就会向服务器进程发送连接请求的SYN同步报文段

SYN=1的报文段称为同步报文段

ISN(Initial Sequence Number)初始序列号

seq序号,即当前发送的报文首字节的编号

 【3. 服务器同意建立连接,回复确认信息,第二次握手

服务器端进程收到连接请求报文,若同意建立连接,从listenfd中获取客户端信息,并且由服务器端操作系统向客户端进程发送SYN报文段给出确认。在确认报文的首部中,SYN=1,ACK=1,确认号ack=x+1 。同时也为自己选择一个初始序号seq = y。这个确认报文也不能携带数据,但同样要消耗一个序号。这时,TCP服务器进入SYN-RCVD(同步报文已收到)状态

TCP协议规定,只要接收方接收到数据,必须给发送方发送确认报文——报文首部ACK标志位为1

ack确认号,期望对方发送的下一个报文首字节的编号

4. 客户端确认连接,发送确认连接信息,第三次握手

客户端进程收到服务器进程的确认报文后,还要向服务器进程的SYN报文给出确认。在确认报文首部,ACK=1,确认号ack=y+1,序号seq=x+1。TCP标准规定,ACK报文可以携带数据,但如果不携带数据,则不消耗序号。在这种情况,客户端进程的下一个数据报文序号仍为seq=x+1。客户端在发送确认报文后,认为连接成功建立,先进入ESTABLISHED(已建立连接)状态

当服务器端进程收到客户端发送的确认报文后,认为连接成功建立,进入ESTABLISHED(已建立连接)状态

上面给出的TCP连接建立过程叫做“三次握手”。注意,上图服务器发送给客户端的报文,也可以拆分为两个报文,即先发送ACK=1(ack=x+1)的确认报文,再发送SYN=1(seq=y)的同步报文。客户端收到服务器端的同步报文段,发送确认报文,过程会变成“四次握手”,但效果一样

2. TCP连接建立相关问题

问题1:TCP建立连接可以只有2次握手吗?

回答:肯定不行。理由:在握手过程中,我们看到客户服务分别在最后一次握手建立连接。如果是两次握手,那么最后的报文由服务器发送,客户端接收

如此,服务器就会先于客户端建立连接。这是万万不可的。

  1. 如果确认报文丢失,那么服务器就会维护不成功的TCP连接
  2. 会很容易遭受SYN洪水攻击,即攻击者发送大量SYN请求,两次握手会使得服务器对每个送达的SYN都建立连接,如此会消耗大量资源,容易导致服务器崩溃
  3. 出现已失效的连接请求报文突然又传送到服务器端,维护失效的连接

“已失效的连接请求报文”是如何产生的呢?

假定一种异常情况:客户端A发送的第一个连接请求报文在某个网络结点滞留了,延误到客户端A认为该报文丢失失效,本次连接失败时,请求报文到达了服务器B。此时该请求报文已经失效,但B并不知道,所以给客户端A发送确认报文,如果只有两次握手,那么此时服务器B发出确认报文,建立连接,进入ESTABLISHED状态

由于A没有再发出建立连接的请求,因此不会处理B的确认报文,也不会向B发送数据。但B却认为连接成功建立,并一直等待A发送数据,浪费资源

所以握手次数绝不能是偶数次,因为这样会使得服务器先建立连接,将维护连接的成本嫁接给服务器


问题2:TCP连接建立为什么需要3次握手?

理由一:奇数次握手,客户端优先建立连接。

理由二:防止已失效的连接请求报文突然又传送到了服务器端,因而产生错误。

理由三:三次握手是客户服务器验证双方信道通畅发送接收能力无误的最小成本

  • 一二次握手,验证了客户端的发送和接收能力
  • 二三次握手,验证了服务器端的发送和接收能力

问题3:在TCP连接建立过程中,如果服务器一直收不到客户端的ACK确认报文,会发生什么?

操作系统会给每个处于SYN-RCVD状态的服务器进程设定一个计时器,如果超过一定时间还没有收到客户端第三次握手的ACK确认报文,将会重新发送第二次握手的确认报文,直到重发达到一定次数才会放弃


问题4:初始序列号ISN为什么要随机初始化?

seq序号表示的是发送的TCP报文数据部分的起始字节位置,服务器/客户端可以通过序号正确读取数据。如果不是随机分配起始序列号,那么黑客就会很容易获取客户端与服务器之间TCP通信的初始序列号,然后通过伪造序列号让通信主机读取到携带病毒的TCP报文,发起网络攻击


问题5:SYN洪水攻击如何解决

SYN洪水攻击:攻击者在短时间内伪造大量不存在的IP地址,向服务器不断地发送连接请求的SYN同步报文。服务器需要为每个请求发送SYN-ACK确认报文,并等待客户端的确认,但因为是不存在IP地址,所以要像问题三中那样,不断发送SYN-ACK确认报文,直到重发到一定次数才会放弃,但这样同样消耗资源。

解决方法:

  1. 缩短SYN Timeout时间。由于SYN洪水攻击的效果取决于服务器上保持的半连接数,这个值=SYN攻击频率*SYN Timeout,所以通过缩短从接收到SYN报文到确认这个报文失效并丢弃的时间,可以成倍地降低服务器的载荷
  2. 设置SYN Cookie。给每一个连接请求的IP地址分配一个Cookie,如果短时间内连续收到某个IP地址的大量重复SYN报文,就认定收到了攻击,以后这个IP地址的报文将直接丢弃
  3. 使用防火墙。SYN 洪水很容易就能被防火墙拦截

二. 释放连接——四次挥手

TCP连接的释放可以用“四次挥手”的过程来描述。数据传输结束后,通信双方都可以释放连接。现在客户端和服务器都处于ESTABLISHED状态。释放连接的过程如下图所示:

1. 四次挥手过程描述

1. 客户端主动断开连接,调用close(fd)发送释放连接的FIN报文,第一次挥手

客户端进程调用close(fd)关闭套接字,操作系统发送释放连接的FIN结束报文,并停止发送数据,主动关闭TCP连接。在结束报文的首部,标志位FIN=1序号字段seq=u,等于前面已发送的数据的最后一个字节的序号+1.此时客户端进入FIN_WAIT_1(终止等待)状态,等待服务器发送确认报文。

TCP规定,FIN报文即使不携带数据,也要消耗一个序号。与SYN报文一样

2. 服务器收到客户端发送的结束报文,发出确认报文段,第二次挥手

服务器收到客户端发送的释放连接的FIN结束报文,立即发送确认报文确认号ack=u+1,序号seq=v,等于服务器前面已发送的数据的最后一个字节的序号+1。服务器进入CLOSE_WAIT(关闭等待)状态。TCP服务器进程此时通知上层应用程序,客户端不向服务器发送数据了,但服务器若有数据发送,客户端仍要接收,此时TCP连接处于半关闭(half-close)状态。

客户端收到服务器的确认报文后,进入FIN_WAIT2(终止等待2)状态,等待服务器发送的FIN结束报文

3. 服务器调用close(connfd)关闭套接字,释放连接,发送FIN结束报文,第三次挥手

当服务器没有要向客户端发送的数据时,其应用进程调用close(connfd)通知TCP释放连接,向客户端发送FIN结束报文。结束报文中,FIN=1,假定序号seq=w(半关闭状态,服务器可能还发送了一些数据),同时还必须重复上次已发送过的确认号ack=u+1。此时,服务器进程进入LAST_ACK(最后确认)状态,等待客户端确认。

4. 客户端收到服务器的FIN结束报文,发送确认报文,第四次挥手

客户端在收到服务器的FIN结束报文后,向服务器发送ACK确认报文。在报文首部中,ACK=1,确认序号ack=w+1,序号seq=u+1(第一次挥手的FIN报文消耗一个序号)。然后客户端进入TIME_WAIT(时间等待)状态

此时TCP连接还没有释放掉,必须经过时间等待计时器(TIME_WAIT timer)设置的时间2MSL后,A才进入CLOSED状态,时间MSL(Maximum Segment Lifetime,最长报文寿命)即一个TCP报文存活的最长时间。RFC793建议2分钟,现在可以根据情况使用更小的MSL值。因此客户端进入TIME_WAIT状态,要经过4分钟才进入CLOSED状态,才可以建立下一个连接,当客户端撤销相应的传输控制块TCB,才结束这次TCP连接

服务器只要收到客户端的确认报文,就进入CLOSED状态。同样,服务器在撤销相应的传输控制块TCB后,就结束此次TCP连接

可以发现,先发起释放连接请求的一方,后结束TCP连接

2. TCP连接释放相关问题

问题1:为什么建立连接是三次握手,关闭连接是四次挥手

首先,建立连接也可以是四次握手,中间的SYN和ACK可以分成两次报文。其次关闭连接,中间服务器给客户端发送的确认报文和FIN结束报文也可以合并,但可能服务器方还有数据需要传输,FIN结束报文在上层调用close()时发送,此时服务器已没有数据传输。

发送FIN报文,只是表示本端不再继续发送数据,但还可以接收数据。TCP通信时全双工的,收到FIN报文,只是关闭一个方向的连接,此时TCP处于半关闭状态


问题2:为什么客户端在TIME_WAIT需要等待2MSL才进入CLOSED状态

理由一:保证客户端发送的最后一个ACK报文能到达对端,保证可靠的终止TCP连接。因为如果出现网络拥塞,该报文可能丢失,因而会使LAST_ACK状态的服务器收不到确认报文,而超时重传FIN报文,而客户端能在2MSL时间内收到重传的FIN报文。接着客户端重传一次确认,重新启动2MSL计时器。最后双方正常进入CLOSED状态

理由二:防止已失效的连接请求报文出现在本次TCP连接。客户端在发送完最后一个ACK报文后,再经过2MSL后,就可以使本次TCP连接持续时间内所产生的所有报文都从网络上消散。这样可以使下一个新的TCP连接不会出现之前旧的请求报文


问题3:TIME_WAIT状态何时出现?TIME_WAIT会带来哪些问题?

TIME_WAIT状态是主动发起关闭连接的一方在收到对方发送的FIN结束报文,并本端发送ACK报文后的状态。

TIME_WAIT的引入是为了让TCP报文得以自然消散,同时为了让被动关闭的一方能够正常关闭连接

  • 服务器主动关闭连接:短时间关闭大量客户端连接,会出现大量TIME_WAIT状态,此时TCB并没有释放,占据大量的tuple(源IP地址、目的IP地址、协议号、源端口、目的端口),严重消耗着服务器的资源。
  • 客户端主动关闭连接:短时间内大量的短连接,会大量消耗客户端主机的端口号,毕竟端口号只有65535个,断开耗尽了,后续就无法启用新的TCP连接了。

问题4:解决TIME_WAIT状态引起的bind()函数执行失败

问题场景:因为主动关闭连接最终会进入TIME_WAIT状态,此时bind的IP地址,端口号都没有释放,重新启动服务会导致bind端口号失败。

解决方法:可以使用setsockopt()函数,设置socket描述符的SO_REUSEADDR选项,该选项可以让端口号被释放后立即再次使用,表示允许创建端口号相同但IP地址不同的多个socket描述符


问题5:半连接,半打开,半关闭的区别
半连接:在TCP连接建立的三次握手中,主动发起连接请求的一方不发最后一次的ACK确认报文,使得服务器阻塞在SYN_RCVD(同步收到)状态

半打开:如果TCP通信一方异常关闭(如断网,断电,进程被kill掉),而通信对端并不知情,此时TCP连接处于半打开状态,如果双方不进行数据通信,是无法发现问题的。解决方法是引入心跳机制,设置一个保活计时器(keepalive timer),以检测半打开状态,检测到就发送RST复位报文,重新建立连接

半关闭:主动发起连接关闭请求的一方A发送了FIN结束报文段,对端B回复了ACK确认报文段后,B并没有立即发送本端的FIN结束报文段给A。此时A端处于FIN_WAIT-2(结束等待2)状态,A仍然可以接收B发送过来的数据,但是A已经不能再向B发送数据了。这时的TCP连接为半关闭状态。


补充:

 在Socket编程中,服务器Listen的第二个参数

三次握手是操作系统自助完成的,但服务器需要accept返回,才会拿到客户端的连接信息。如果服务器没有accept,这个连接就是全连接backlog是全连接队列的容量-1

Linux内核协议栈为TCP连接管理使用两个队列:

  • 半连接队列(用来保存SY_SENT和SYN_RECV状态的请求)
  • 全连接队列(accept队列,用来保存处于ESTABLISHED状态,但应用层没有调用accept取走的请求)

三. TCP状态转换

为了更清晰地看出TCP连接的各种状态之间的关系,下图给出了TCP的状态转换示意图。

说明:紫色框框是TCP状态,红色是服务器进程的正常状态转换,蓝色是客户端进程的正常状态转换,黑色是异常变迁,即出现问题时的状态转换。

服务端状态转化:

  • CLOSE -> LISTEN】:服务器端调用listen后进入LISTEN状态,等待客户端连接
  • LISTEN -> SYN_RCVD】:一旦监听到连接请求(同步报文段),就将该连接放入内核等待队列,并向客户端发送SYN确认报文
  • SYN_RCVD -> ESTABLISHED】:服务端一旦受到客户端的确认报文,进入ESTABLISHED状态,可以进行读写数据
  • ESTABLISHED -> CLOSE_WAIT】:客户端主动关闭连接(调用close),服务器会受到结束报文,服务器返回确认报文并进入CLOSE_WAIT
  • CLOSE_WAIT -> LAST_ACK】:进入CLOSE_WAIT后说明服务器准备关闭连接(需要处理完之前的数据);当服务器调用close关闭连接时,会向客户端发送FIN结束报文,进入LAST_ACK状态,等待客户端发送FIN结束报文的ACK确认报文
  • LAST_ACK -> CLOSED】:服务器收到了对FIN结束报文的ACK确认报文,释放连接,撤销传输控制块TCB,释放相应的连接管理资源

客户端状态转化:

  • CLOSED -> SYN_SENT】:客户端调用connect(),发送SYN同步报文段
  • SYN_SENT -> ESTABLISHED】:connect()调用成功,进入ESTABLISHED状态,开始读写数据
  • ESTABLISHED -> FIN_WAIT1】:客户端主动调用close(),向服务器发送FIN结束报文段,同时进入FIN_WAIT1状态
  • FIN_WAIT1 -> FIN_WAIT2】:客户端收到服务器发送的对FIN结束报文的ACK确认报文,则进入FIN_WAIT2状态,开始等待服务器的FIN结束报文
  • FIN_WAIT2 -> TIME_WAIT】:客户端收到服务器发送的FIN结束报文,进入TIME_WAIT状态,并发送最后一个ACK确认报文
  • TIME_WAIT -> CLOSED】:客户端等待2MSL时间,才会进入CLOSED状态,释放连接资源

结束语

本篇博客到此结束,感谢看到此处。
欢迎大家纠错和补充
如果觉得本篇文章对你有所帮助的话,不妨点个赞支持一下博主,拜托啦,这对我真的很重要。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android 性能优化一篇解决

前言 使用java编写的源代码编译后生成了对于的class文件,但是class文件是一个非常标准的文件,市面上很多软件都可以对class文件进行反编译,为了我们app的安全性,就需要使用到Android代码混淆这一功能。针对 Java 的混淆&#xff…

不同版本QT使用qmake时创建QML项目的区别

不同版本QT使用qmake时创建QML项目的区别 文章目录 不同版本QT使用qmake时创建QML项目的区别一、QT5新建QML项目1.1 目录结构1.2 .pro 文件内容1.3 main.cpp1.4 main.qml 二、QT6新建QML项目2.1 目录结构2.2 .pro文件内容2.3 main.cpp2.4 main.qml 三、两个版本使用资源文件的区…

DSO在Euroc上运行经验贴,关于时间戳为0的结局方法

网上DSO基本上都是在TUM数据集上跑得,教程也比较多,写论文需要,使用DSO跑了一下Euroc数据集,踩了很多坑,花了一天的时间才调通,记录一下。 本机运行环境:Ubuntu16.04 其它环境只要安装过ORB-SA…

10.鸿蒙应用程序app创建第一个程序Helloworld

鸿蒙应用程序开发app_hap开发环境搭建 1.打开DevEco 2.创建项目 3.选择Empty Ability 4. 选择API6,支持java开发 5.点击Finish 6.启动本地模拟器参考方法 7.启动成功 8.运行程序 9.运行成功 其它文章点击专栏

龙芯loongarch64服务器编译安装gcc-8.3.0

前言 当前电脑的gcc版本为8.3.0,但是在编译其他依赖包的时候,出现各种奇怪的问题,会莫名其妙的中断编译。本地文章讲解如何自编译安装gcc,替换系统自带的gcc。 环境准备 下载页面:龙芯开源社区网站 - LoongArch GCC 8.3 交叉工具链 - 源码下载源码包名称如:loongson-gnu…

【每日一题】—— C. Largest Subsequence(Codeforces Round 915 (Div. 2))(规律、字符串处理)

🌏博客主页:PH_modest的博客主页 🚩当前专栏:每日一题 💌其他专栏: 🔴 每日反刍 🟡 C跬步积累 🟢 C语言跬步积累 🌈座右铭:广积粮,缓称…

Postman使用总结--关联

当接口和接口之间,有依赖关系时,需要借助 postman 关联技术来实现

计算机组成原理——数据的表示与运算2

D n位定点整数包括1位符号位,n-1位数值位。因此当符号位为0,表示为正数时,数值位全为1,是最大值。例如n5,那么01111是最大值,最大值是15。 111110000-12^4-1 最小值只要符号位取1即可,所以最…

福德植保无人机工厂:创新科技与绿色农业的完美结合

亲爱的读者们,欢迎来到福德植保无人机工厂的世界。这里,科技与农业的完美结合为我们描绘出一幅未来农业的新篇章。福德植保无人机工厂作为行业的领军者,以其领先的无人机技术,创新的理念,为我们展示了一种全新的农业服…

超级计算机与天气预报:精准预测的科技革命

超级计算机与天气预报:精准预测的科技革命 一、引言 随着科技的飞速发展,超级计算机已经成为现代社会不可或缺的一部分。它们在科研、工业、军事等领域发挥着重要作用,其中天气预报是一个颇具代表性的应用领域。本文将探讨超级计算机在天气…

VueDraggablePlus - 免费开源的 Vue 拖拽组件,支持 Vue2 / Vue3,还被尤雨溪推荐了

今天在网上看到尤雨溪推荐的这款拖拽组件,试了一下非常不错,同样推荐给大家。 VueDraggablePlus 是一个专为 Vue 打造的拖拽排序模块,基于 Sortablejs 封装,支持 Vue3 或 Vue 2.7,本月的 21 日,Vue 作者尤…

钡铼无线R10A工业级路由器在工业机器人领域的创新应用

随着工业机器人的普及,对于高可靠性和高稳定性的网络接入设备的需求也越来越大。传统的有线网络虽然稳定,但在现场布置和维护上面临很多困难,而无线网络虽然方便,但受到信号干扰和传输距离限制等问题的影响。如何解决这些问题&…

word增加引用-endnote使用

使用软件: web of science https://webofscience.clarivate.cn/wos/alldb/basic-search; Pub Med等数据库endnote20 链接: https://pan.baidu.com/s/1VQMEsgFY3kcpCNfIyqEjtQ?pwdy1mz 提取码: y1mz 复制这段内容后打开百度网盘手机App,操作更方便哦 --…

Hadoop Single Node Cluster的安装

Hadoop Single Node Cluster的安装 安装JDK查看java -version更新本地软件包安装JDK查看java安装位置 设置SSH无密码登录安装hadoop下载安装设置hadoop环境变量修改hadoop配置设置文件设置core-site.xml设置YARN-site.xml设置mapred-site.xml设置HDFS分布式文件系统创建并格式化…

新增工具箱管理功能、重构网站证书管理功能,1Panel开源面板v1.9.0发布

2023年12月18日,现代化、开源的Linux服务器运维管理面板1Panel正式发布v1.9.0版本。 在这一版本中,1Panel引入了新的工具箱管理功能,包含Swap分区管理、Fail2Ban管理等功能。此外,1Panel针对网站证书管理功能进行了全面重构&…

小程序自定义轮播图样式

小程序自定义轮播图样式以下是各案例&#xff0c;仅供大家参考。 效果展示&#xff1a; index.wxml代码&#xff1a; <view><!-- 轮播 --><view><swiper indicator-dots"{{indicatorDots}}"autoplay"{{autoplay}}" interval"{{…

初识迭代器(Iterator)——迭代器模式——迭代加深(后续更新...)

学习网页&#xff1a; Welcome to Python.orghttps://www.python.org/ 迭代器&#xff08;Iterator&#xff09; 迭代器是一个非常有用的Python特性&#xff0c;它允许我们遍历一个容器&#xff08;如列表、元组、字典、集合等&#xff09;的元素。迭代器提供了一种方法&…

OpenHarmony应用开发环境搭建指南

OpenHarmony的应用开发主要是基于Deveco Studio&#xff08;目前只支持Windows及Mac平台&#xff09;搭配相应的SDK进行&#xff0c;现对开发环境的搭建进行说明。 1:Deveco下载安装 下载对应平台的安装包即可。接下来以Windows平台为例&#xff0c;进行开发环境的搭建。 下载…

我做了一个在手机灵动岛锁屏看实时网速/步数/下班倒计时/跑步距离/照片/待办/倒计时/手机使用次数/帧率...的软件

我做了一个在手机灵动岛&锁屏看实时网速/步数/下班倒计时/跑步距离/照片/待办/倒计时/手机使用次数/帧率…的软件 Island Widgets 的作用&#xff1a; 提醒您 &#xff1a; 准时下班每天运动陪伴家人保持体重放下手机每日待办当前网速手机使用强度实时热搜现在天气… 初…

小米与魅族:竞争中的创新之路

导言 小米与魅族作为中国智能手机领域的两大明星企业&#xff0c;一直在激烈的竞争中谋求创新突破。本文将深入探讨这两家公司在产品、市场和创新方面的竞争与合作&#xff0c;揭示它们在快速发展的移动科技行业中的发展轨迹。 1. 产品创新与竞争 小米的性价比…