当前位置: 首页 > news >正文

Linux网络:TCP

文章目录

  • 1. TCP简介
  • 2. TCP报头
  • 3. TCP机制
    • 3.1 确认应答机制
    • 3.2 超时重传机制
    • 3.3 连接管理机制
      • 3.3.1 三次握手
      • 3.3.2 四次挥手
      • 3.3.3 详解TIME_WAIT
    • 3.4 滑动窗口
    • 3.5 流量控制
    • 3.6 拥塞控制
    • 3.7 延迟应答
    • 3.8 TCP机制总结
  • 4. TCP粘包问题
  • 5. TCP异常情况
  • 6. TCP应用

1. TCP简介

TCP全称是transmission control protocal,即传输控制协议,顾名思义,不同于UDP的无连接和不可靠,TCP要对整个网络通信过程,做详细控制。也正因为要做控制,所以TCP的底层设计要远远比UDP复杂。

2. TCP报头

在这里插入图片描述
从TCP报头入手,介绍报头结构,TCP所有底层控制机制都可以从报头的数据中延申出去。

源端口和目的端口不再赘述。

32位序号和32位确认序号是什么呢?这个与TCP确认应答机制有关,后文再说。

4位首部长度说明TCP报头结构的可扩展性,4位首部长度数据表示了TCP报头总共有几个四字节——4个二进制位表示的数据大小在0~15,因此TCP报头最大长度为60字节,至少是20字节,可扩展部分为40字节。

接下来是6个标志位。

URG:紧急指针标志位。表示所传的数据中,存在紧急数据,数据大小只能为1字节,通常代表一个任务码,该字节在有效载荷的偏移量由16位紧急指针标明

ACK:确认应答标志位。通常与确认序号一起使用,告诉数据发送方,确认序号前的数据已经受到,下次发送数据从确认序号开始发(由于存在捎带应答的情况,ACK通常都置为1)。

PSH:推标志位。发送该标志位时,一般是接收方接收缓冲区一直保有大量有效数据,致使窗口大小太小,使得发送方无法发送数据或发送效率低下,此时发送该标志位,即告诉接收方,尽快将接收缓冲区中的数据取走。

SYN:同步标志位。通常是TCP三次握手中,请求建立连接时发送的,我们把携带该标志位的报文段,称为同步报文段

RST:重置标志位。表示对方要求重新建立连接,即重新进行TCP三次握手过程,重置报文段。
FIN:结束标志位。通知对方,本端要关闭了,通常出现在TCP四次挥手过程中,结束报文段。

16位窗口大小,这个上文已经讲过,是用来描述接收方接收缓冲区当前接受能力的,但是并不就是0~65535字节.TCP报头中,存在选项,即可扩展部分,其中有一个可以是窗口扩展因子,实际的窗口大小,应是16位窗口大小左移窗口扩展因子这么大的位数。

16位检验和:这个字段在UDP中也出现过,是用来确认网络传输过程中,报文整体是否被修改的字段。

3. TCP机制

UDP是无连接,不可靠,面向数据报的;TCP是有连接,可靠,面向字节流的。
TCP的连接,可靠,面向字节流是有一套底层机制进行维护的,现在我们就来介绍这套机制。

3.1 确认应答机制

TCP中,将要发送的数据每个字节都编号,确认一个随机的起始序号后,接下来发送的数据,每个字节就从该序号开始增长编号。

那么,为什么要编号呢?
再看向TCP报头,其中存在一个字段32位确认序号,这个序号与确认应答机制结合,可以用来告诉发送方,在该确认序号之前的数据都已收到,下次发送,请从确认序号对应的数据开始发。
这样,就保证了发送方知道自己发送的数据,哪些对方收到了,哪些对方没有收到,进而确认是否要重发。

TCP是面向字节流的,并不像UDP那样,有明确字段规定16位UDP长度,规定出明确的数据边界;TCP字节流式的数据传输,如何告诉发送方自己究竟收到哪些数据呢——通过确认应答机制实现。

一方面,确认应答机制保证了未接收到的数据对端可以重发;同时,发送方给每个字节的发送数据编号,使得接收方可以根据编号,有序排列数据,比如序号大的数据先传输到了,那么先暂存,不立刻放入接收缓冲区中,等前面的数据到后,再一起放入缓冲区中——因此,TCP中的数据传输,保证有序性,这点是UDP中无法做到的。

3.2 超时重传机制

在上述确认应答过程中,可能存在丢包问题。

丢包问题一般都分为两种:一种是数据包丢失,一种则是数据包未丢失,但是数据包的确认应答ACK丢了。

无论是哪一种,只要最终发送端没有收到确认应答,那么发送端就会统一进行重传。所以,发送端什么时候进行重传,本质就是如何界定超时时间的问题。

但是网络情况本质是有波动的,如果时间设置太长,影响重传效率;如果时间设置太短(实际上并未丢包,只不过ACK确认应答还在网络传输,并未到来),就可能频繁发送相同的数据包。

在Linux中,判定超时重传的时间是以500ms作为基准的,第一次超时时间是500ms,之后的每次超时时间都是 两倍扩增,即指数级增长,当然这个时间不会无限扩增,累计到一定次数后,可能是网络太差,或者对端连接已经异常关闭了,此时就强制关闭该连接。

对接收方而言,如果是数据包丢失,那么不用担心收到重复数据包的问题;但如果是应答丢失,就可能会受到重复数据包,那么如何去重呢?前面有讲到确认序号,接收端通过确认序号就能清楚判断该数据包是否收到,进而做去重处理,重复数据包丢弃即可。

3.3 连接管理机制

TCP通过连接管理机制对网络连接进行维护,正常情况下,TCP通过三次握手建立连接,四次挥手断开连接。

3.3.1 三次握手

首先,明确三次握手过程中,发送的都是TCP报文,通过TCP报文中的标志位,来标明该TCP报文的用途。

主动发起连接的一方发送携带SYN标志位的TCP报文,同时随机一个起始的序号,然后进入SYN_SENT状态。

接收连接的一方收到该携带SYN标志位的报文后,回发一个携带SYN+ACK标志位的TCP报文,SYN同样表示要求与对方建立连接,ACK则是告诉对方,之前的建立连接请求我已收到,相应地,该发送的TCP报文中自身序号需选定一个随机的开始序号,确认序号则是对端的序号加1,然后接收方进入SYN_RCVD状态。

此时之前主动发起连接的一方,收到对端报文后,再次发送携带ACK标志位的TCP报文,同时按照要求维护报文中的序号和确认序号,进入ESTABLISHED,即连接成功建立状态。

另一端,收到该信号后,同样进入ESTABLISHED,即连接成功建立状态。

这就是TCP三次握手的整个流程,那么为什么需要是三次握手呢?

首先,我们要明白,三次握手其实可以被拆成四次握手,因为第二个TCP报文同时携带SYN+ACK标志位,实际上可以分开发,先发ACK,再发SYN,这里是捎带应答。

TCP通信本身是全双工的,每一端既可以读,也可以写。那么一个完整TCP连接的建立,为了确保能够正常实现全双工,必须在连接阶段就确认连接双方,每一端都具备读写能力,可以收TCP报文,也可以发TCP报文,或者更具体一点,要让连接双方都知道对方能够与自己交互读写。

从这个角度切入的话,那么整个TCP三次握手过程,本质就是告诉对方自身具备读或写能力的过程。

第一次,一端告诉另一端,我有写的能力。
第二次,一端告诉另一端,我有读写的能力。
第三次,一端告诉另一端,我有读的能力。
至此,双方均已知道另一方具备读写能力,连接建立成功。

需要额外说明的,对于一个纯粹的确认应答报文本身,即该报文不是捎带应答,是不需要再进行确认,即不需要确认确认本身,否则会陷入无限循环的情况。

3.3.2 四次挥手

TCP断开连接过程,是四次挥手。

首先,主动断开连接的一方(既然是主动断开连接,肯定已经走完相关读写逻辑)通过close(sockfd),TCP传输层发送携带FIN标志位的报文,然后进入FIN_WAIT_1状态。

然后,另一端收到携带FIN标志位的报文,给对端发送ACK确认标志位,进入CLOSE_WAIT状态。为什么是CLOSE_WAIT呢?因为此端接收到该报文时,可能仍处在网络通信的读写逻辑中,需要正常走完所有的读写逻辑后,比如对端关闭,再也读不到数据,返回0,或者因为对端关闭,写返回错误,此时就进入close逻辑中,close(sockfd)

接着,主动断开连接的一方,收到对方的ACK确认报文后,进入FIN_WAIT_2状态,等待对端的FIN报文。

接着,在第二条的逻辑下,被动断开连接的一方完成close(sockfd)后,同样给对端发送携带FIN标志位的报文,进入LAST_ACK状态。

最后,主动断开连接一方收到对端的携带FIN的TCP报文后,发送ACK确认应答,进入TIME_WAIT状态,等待2 * MSL,即2倍的TCP报文最大存活时间后,进入CLOSED状态,连接彻底关闭。
而被动断开连接一方收到对端的ACK后,同样进入CLOSED状态,关闭连接。

针对上述四次挥手中的一些细节,我们进行探讨?

首先,为什么是四次挥手,能不能合并成三次挥手?
不能合并成三次挥手,可能想着通过捎带应答,将中间的ACK+FIN合并在一起,但这是不行的。因为被动断开连接的一方,ACKFIN的时机并不同,还要走完读写逻辑退出后,才close,才发送FIN

那么,四次挥手意义何在?
TCP是全双工通信,通信双方任何一方都可以读写,因此什么时候认为连接关闭——通信双方都不再读写,不再通信。

从这个角度切入,四次挥手的过程,实际上就是告知对端,我不再进行读写,不再通信的过程。
第一次的FIN发送,代表主动断开连接的一方,不再进行读写。
第二次的ACK发送,代表另一方告诉对方,我知道你不再进行读写了。
第三次的FIN发送,代表被动断开连接一方,告诉对方,我已走完所有读写逻辑,不再读写。
第四次的ACK发送,代表主断连接方,告诉对方,我知道了。

自此,双方都知道对方不再进行读写,TCP全双工通信彻底瓦解,TCP四次挥手完成。

上述四次挥手结束后,被动断开连接方正常进入CLOSED状态,关闭连接,可是为什么主动断开连接方,先进入TIME_WAIT状态,等待2MSL后,再进入CLOSED状态呢?

关于TIME_WAIT状态,需要开一个小专题好好讲讲。

3.3.3 详解TIME_WAIT

TIME_WAIT状态,是主动断开连接一方发送最后一个ACK确认报文后,进入的状态。

为什么要有TIME_WAIT状态?
实际上,主动断开连接一方的FIN发送,就内核TCP传输层而言,是告诉对方不再做实际数据写,但是仍可以读,这意味着对端在进入CLOSE_WAIT状态后,走用户层逻辑时,是可以正常发送数据的。那么这些数据需不需要被处理?肯定需要,虽然主动断开连接一方,用户层已没有读写逻辑,但是TCP必须将这些垃圾数据处理,防止影响后续其它网络通信。

处理垃圾数据是TIME_WAIT的一个作用,TIME_WAIT还可以兼顾到最后主动断开连接一方ACK的重发。因为如果最后的ACK对端没有收到,进而重发FIN,那么TIME_WAIT状态下的一方就可以重发ACK,保证TCP四次挥手的完整性。

那么,为什么TIME_WAIT状态是持续2MSL时间,这个时间什么含义。
MSL表示的是Max Segment Life,指的是TCP报文在网络传输中的最大存活时间,在Linux网络通信中,这个时间大小是30S
不是MSL,而是两倍,实际上是做最坏考虑,因为TCP报文发送接收的一个来回理论最大耗时时长就是两倍的MSL,这样可以保证在TIME_WAIT下,将所有的旧数据处理完。
以最后的FINACK为例,主动断开连接方,发送最后一个ACK后,理论上最坏等30s,看对方是否接收到(实际上不可能,超时重传机制500ms为基准),此时,如果对方未接收到,那么重发FIN,TIME_WAIT方最坏等30s,接收到之后就可以重发ACK,解决ACK丢包问题。那么在整个过程中,TIME_WAIT方最坏需要的时间就是2MSL。

就实际而言,2MSL的时间一般都是非常盈余的,但能在理论上保证所有旧数据,旧请求被处理完毕。

主动断开连接的一方会进入TIME_WAIT状态,该状态下,仍然占用端口号,因此会出现其它进程bind此端口失败情况,关于这一点,我们分客户端和服务端分别讲解。

对于客户端而言,一般特别处理TIME_WAIT状态,因为客户端一般都是不主动bind,而是交由系统内核任意bind,因此一般不会存在端口号冲突情况。

对于服务端而言,因为服务器要被客户端访问,端口号是固定的。如果服务器因为意外导致程序终止,此时大量该端口连接进入TIME_WAIT状态,导致服务器无法重新绑定该端口,重启服务,这是绝对不被允许的。

那么,如何解决呢?
一般来说,一个端口只能被一个进程绑定,但是可以通过设置socket选项,使得一个端口,如果其所对应进程处在TIME_WAIT状态,那么允许另外一个进程绑定该端口。
一般使用setsockopt接口这样设置:

int opt = 1;
setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
//设置的是用于监听的fd可以重复绑定,因为服务端就是用listenfd绑定到特定端口的

此时,服务器端就可以重复绑定到同一个端口,进行快速重启。
此时,在该端口上处在TIME_WAIT状态的连接,是否会影响此时重启服务端的通信?
这点,我们要分情况讨论。
首先,在TCP传输层的内核层面,使用一个唯一四元组标识一个连接,即通信双方的IP+PORT,构成这个四元组。
在四元组不同时,连接是不可能受到影响,主要是四元组相同时。
新连接的建立,如果与TIME_WAIT中的旧连接,四元组相同,那么在Linux中的处理行为,通常都是提前终止这个处在TIME_WAIT的连接,然后重新建立新连接,这样就没有冲突了
那么,现在这个四元组对应新连接,旧报文会不会影响到新连接了?首先,四元组对应,旧报文肯定会被接收,但是有两个机制可以规避:

  1. 序号判别。不同TCP连接的起始序号一般差别是很大的,可以通过报文中的序号判断是否为旧连接报文,进而丢弃。
  2. 时间戳判别。在TCP报文中,可以允许一个时间戳选项(TCP报文的扩展部分),代表该TCP报文的时间,对于新连接,不接受时间戳倒退的报文,认为该报文是旧连接垃圾数据,进而丢弃。

上述是新连接建立时,四元组相同,TIME_WAIT状态存在的情况,如果此时TIME_WAIT状态结束了呢,会不会受到旧报文影响呢?
首先,TIME_WAIT状态正常结束,说明已经处理好所有旧数据,新连接不必担心。其次,就算真的收到旧数据,也可以通过上述的序号和时间戳机制进行甄别。

需要额外说明的是,一般来说客户端不会出现重复bind情况,但如果真的出现,或者客户端也手动bind,那么一个端口想要重复bind,仍需要使用setsockopt进行设置,如果四元组相同的话,那么对于处在TIME_WAIT状态的就连接,在进行相关设置后,客户端也能提前终止该旧连接。

最后,关于setsockopt再来讲一点。
上述端口复用,使用SO_REUSEADDR,实际在现代Linux中,引入了SO_REUSEPORT,这个选项比前者更加强大,不仅支持绑定到处在TIME_WAIT端口,还支持正常状态下的多端口绑定,即多个连接均可复用此端口,内核层面会做负载均衡

3.4 滑动窗口

TCP的数据发送与接收遵守确认应答机制。
但如果数据发送是这样的,一端发出,一端接收返回确认应答,发出端必须接到确认应答后,才能发送下一段数据,这样效率就太低了。

为什么效率低?因为每次数据发送,这段数据在网络中的传输时间都是独立的,并不重合,没有很好复用同一段网络传输时间。

因此,如果允许即便在没有收到确认应答前,也可以连续发送多批数据,这批数据的发送不需要受到确认应答限制,那么这样就可以复用网络发送时间,提高通信效率。

在上述场景下,不用确认应答,允许发送的最大数据量,就表示滑动窗口大小,即滑动窗口范围内,是无需等待确认应答就可继续发送的数据。

上述其实并未讲清楚,滑动窗口实际到底是如何实现的,即没有一个实际轮廓。

实际上,滑动窗口使用在数据发送中的,滑动窗口本身就是发送缓冲区的一部分,简单理解,两个变量,分别代表发送缓冲区中滑动窗口的起始位置和结束位置,就实现发送缓冲区中的滑动窗口。

在这里插入图片描述
滑动窗口实际工作时,将窗口中的数据连续发出后,收到确认应答,比如收到确认序号为2001,说明1001-2000的数据对端收到,那么滑窗左边界就向右移动。此时滑窗右边界向右移动,将5001-6000的数据再次发出(实际滑窗大小受到网络和对端接收能力双重限制,后面再说)。

关于滑窗,其实有一些细节。
首先,上图所呈现的TCP发送缓冲区是线性连续的,实际上TCP缓冲区并非如此,但是逻辑上我们可以按照线性来理解。
第一个细节,为什么滑窗是从左向右滑?
因为整个发送缓冲区,数据的存储是从左向右存,开始数据存低地址起始,后面数据存高地址,数据存储顺序决定了滑窗滑动顺序。

第二个细节,滑窗实际上将整个发送缓冲区分为三部分。
滑窗前,滑窗中和滑窗后。
滑窗前数据是已经收到确认应答的数据,这些数据可以被丢弃或覆盖。
滑窗中数据是已经发送但未收到确认应答的数据,这些数据不能被覆盖。
滑窗后数据是还未发送的数据。

第三个细节,发送缓冲区中,如果全部数据发完了,之后怎么办?
有这个问题,其实是我们上图和理解TCP缓冲区的局限,我们可以将TCP缓冲区理解为一个线性的环形缓冲区,这样滑动窗口即可周而复始滑动。

最后,基于滑动窗口和确认应答机制讲一讲丢包问题和快重传机制。

我们将丢包分为两种情况。

数据包正常抵达,但是ACK丢失了。
在滑动窗口中,由于连续发多批数据,中间的某一个ACK丢失没关系,因为后面到达的ACK可以进行确认——确认序号表示该序号之前的数据都已收到,所以此时发送端无需重传。当然,如果所有ACK都丢,那么没办法,只能重传。

数据包丢失,未正确抵达。
比如说1~1000数据对端正常接收,但是1001-2000丢失,那么有一种机制叫做快重传,接收方此时连续发送三次确认序号为1001的确认应答,发送方连续收到三次这样的确认应答,就知道1001-2000数据包丢失了,于是立刻重发。

上述快重传机制是与超时重传机制互相补充的。快重传,在一个字,能够尽快重传,提效率;超时重传,保一个下限,即最终超过限定时间后,发送方依旧会进行重传。

3.5 流量控制

网络通信,不仅仅是发送方发送,同样要兼顾接收方接收。如果发送方发送太快,远大于接收方接收能力,那么没有任何意义。

因此,流量控制本质是通过接收方的接受能力,对发送方进行发送速率的限制。

那么,发送方如何知道接收方的接收能力呢?
TCP报文中,有16位窗口大小,这个字段,就是表示接收方TCP接收缓冲区目前的接收能力。

所以,可以通过TCP报文告诉发送方自身的接收能力。在TCP三次握手中,交换的TCP报文中,就已经携带了窗口大小信息。

实际控制中,接收方将自身TCP接收缓冲区中的剩余字节数填入该字段中。发送方收到后,根据这个字段,动态调整自身的滑动窗口大小。
比如说,收到TCP报文中,这个字段大小为4000字节,而此时滑动窗口中数据大小恰好为4000字节。之后收到应答,对端成功接受了1000字节,窗口大小变为3000字节,此时滑动窗口只能缩小,不能扩大,因为对端接收能力此时只有3000字节,此时滑窗中内容刚好3000字节,这些内容是已经发送,但对方还未收到并回复ACK的数据,数据量大小刚好等于对端接收能力,因此滑窗不能再右移,做额外发送了。

3.6 拥塞控制

网络通信,除了与发送方和接收方有关,还与传输媒介网络相关。网络的好坏情况,是直接影响数据传输的。

但网络是会动态波动的,我们无法直接限定一个发送速率,否则如果相比于这个速率,网络显得过于拥堵,那么以这个速率发送就会加剧网络拥堵情况,如果全网主机都如此处理,那么最终导致根本无法正常进行数据发送;同时,如果相比之下,网络又显得过于通常,那么此时以该速率发送,未充分利用网络资源,效率太低。

网络是动态波动的,因此,我们也应该根据其波动情况做动态调整。

为了解决这个问题,TCP引入慢启动机制,即先发少量数据探入,摸清当前网络的拥堵状态后,再决定按照多大速率传输。

对于慢启动机制,引入一个概念拥塞窗口
拥塞窗口有一个初始值,开始时比较小,随后进行数据发送,每收到一个ACK应答后,拥塞窗口就扩大。实际上,拥塞窗口大小与上述接收方窗口大小共同限制了发送方滑动窗口大小,二者大小中取较小值,就是实际滑窗大小。

慢启动机制下,拥塞窗口初始值比较小,但增长非常快,是指数级别的增长速率,显然不能让滑动窗口一直保持指数级别增长速率,因此引入一个慢启动阈值

实际拥塞窗口达到或超过该慢启动阈值后,之后拥塞窗口的增长将保持线性速度。
那么,如果此时网络情况突然拥堵,拥塞窗口如何改变呢?
如果网络情况突然拥堵,发送出去的报文迟迟没有收到应答,触发超时重传,那么此时直接将拥塞窗口大小缩小到初始值,并且乘法缩小慢启动阈值,然后重走上述慢启动逻辑。

因此,引入拥塞控制后,TCP通信启动后,网络吞吐量逐渐上升;发生网络拥堵后,网络吞吐量下降。

上述的整个逻辑,就是TCP的拥塞控制,下面讲几个细节。

第一个细节,拥塞窗口会无限增长吗?
理论上,拥塞窗口确实能无限增长,但是即便在最理想的网络情况下,也无法做到传输无限的数据,因为网络本身有带宽的限制,一次性能传输的最大数据始终不能超过网络带宽。

第二个细节,为什么超时重传时,调整拥塞窗口大小。
拥塞窗口本身根据网络情况做动态调整,而发生超时重传,往往是发生在网络变拥堵的情况下,因此超时重传是能够反映网络情况的。

3.7 延迟应答

什么是延迟应答呢?
如果接收方收到数据后,总是立刻应答,那么可能此时返回的窗口就较小,而如果等一会儿再应答,可能TCP接收缓冲区中的数据就被大量取走,此时窗口大小就很大。
而接收方窗口大小,最终会直接影响到TCP通信中的网络吞吐量,而网络吞吐量直接反映网络通信效率。
因此,延迟应答是很有意义的。
那么,需不要每个应答都做延迟应答呢?
实际处理中,并未这样。通常有数量和时间上的限制。数量限制是指每隔几个包就延迟应答一次,时间限制是指每隔一定时间就延迟应答一次。

3.8 TCP机制总结

TCP的上述复杂机制,带来了TCP面向连接,可靠性的特点。
连接管理机制维护了TCP面向连接的特性,而维护连接,本质也是对可靠性的维护,因为连接的建立过程中,本身就有为确认应答机制做准备,也有涉及流量控制。

而确认应答机制和超时重传机制,保证了通信双方在网络中进行数据传输的可靠性。

而滑动窗口,流量控制,拥塞控制这三者是息息相关的,可以这么说,因为TCP要保证可靠性的特点,所以设计了各种机制,而滑动窗口就是落实这些机制的具体结构实现。

对于流量控制,拥塞控制,在对端接收能力强,网络通畅时,保证了通信效率;而在对端接受能力弱,网络拥塞时,又何尝不是保证了通信的可靠性呢——此时就少发数,发太多数据,对方可能都接收不到,或者接收到了,也因为接收能力弱,而丢弃多余数据。

因此,TCP各种复杂机制的设计,总是以一点为核心:在保证网络通信可靠性的前提下,尽可能提升网络通信效率。

4. TCP粘包问题

UDP是面向数据报的,接收UDP报文时,内核保证了有效载荷接收的完整性,划定了数据边界,用户层的代码可以直接读取——要么读到完整报文,要么就读不到。

但是TCP面向字节流,内核并不维护数据的完整性,需要在应用层自己解决粘包问题。因此,在TCP通信中,粘包问题的解决,是应用层协议要关心的内容。

以下介绍几种简单的粘包问题解决方案:
如果发送数据是定长的,那么接收方同样定长读取,即可收到完整数据
如果发送数据是变长的,那么可以在发送数据的开始,用固定长度的字节表示有效载荷大小,或者不在数据开始添加大小信息,而是在数据结尾使用同一符号,标识数据结束,如\r\n,等等。

5. TCP异常情况

TCP异常情况,主要是指TCP断开连接时会遇到的一些特殊情况。

进程异常终止。进程异常终止,最终操作系统内核依然要正常回收该进程相关资源,此时TCP连接断开的过程,和正常断开没有区别。

机器正常关机或重启。本质上机器正常关机或重启,在关机或重启前,依然要处理所有进程,释放进程相关资源,和进程异常终止时情况相同。

机器突然掉电关闭或者网线突然断开。这种情况,是没有走TCP四次挥手逻辑的,即通信的另一方此时是不知道对方连接已断开,该TCP通信出问题了。此时读行为会阻塞,而写行为会不断触发超时重传,达到一定次数后,发送携带RESET标志位的报文,要求对方重新建立连接,当然,这肯定也没有任何作用,最终内核可能会强制关闭该连接。

实际上,对于连接的状态检测,TCP内置有一个保护定时器,在某个连接持续空闲时,会定期询问连接对端是否还在,如果不在,也会把连接释放。
TCP的保活定时器间隔时间太长,当一个连接空闲2h,才会触发相关逻辑,无法精确跟踪连接状态,因此通常都会在用户层主动维护TCP心跳保持逻辑,实现秒级检测。

6. TCP应用

TCP面向连接,保证可靠性和效率性的特点,使得TCP应用非常广泛。

有大量的应用于不同领域的应用层协议都是基于TCP的:

  1. Web服务。使用最为广泛的http/https(用于网页浏览),以及WebSocket
  2. 文件传输。比如应用层的FTP协议。
  3. 邮件传输。SMTP协议。
  4. 远程访问。SSH,telnet等。
  5. 数据库。Mysql,MongoDB等。
http://www.dtcms.com/a/511136.html

相关文章:

  • HarmonyOS 5 鸿蒙应用性能优化与调试技巧
  • 商业网站可以选择.org域名吗勒索做钓鱼网站的人
  • 博客类网站模板网站的维护与更新
  • 【NVIDIA-H200-4】4节点all-reduce-从单节点到四节点的性能跃迁:NVIDIA H200 集群扩展的全链路分析
  • 纯干货呈现!红帽认证最全解析,您想了解的尽在其中
  • 《数据库系统》SQL语言之复杂查询 子查询(NOT)IN子查询 θ some/θ all子查询 (NOT) EXISTS子查询(理论理解分析+实例练习)
  • leetcode 844 比较含退格的字符串
  • 本地neo4j图谱迁移至服务器端
  • 【线规UL认证】入门线规标准要求有一些
  • Allure离线安装指南:支持Windows和Linux系统
  • CoolGuard更新,ip2region升级、名单增加过期时间
  • 济南道驰网站建设有限公司怎么样宝安网站-建设深圳信科
  • UE5 材质-11:继续石头与苔藓,把渐变系数引入到法线中,
  • 跨境电商网站建设成本wordpress自定义文章排列顺序
  • agent设计模式:第三章节—并行化
  • Rust语言特性深度解析:所有权、生命周期与模式匹配之我见
  • 利用DuckDB rusty_sheet插件0.2版在xlsx文件中测试tpch
  • 设计模式之:单例模式
  • 第一章 不可变的变量
  • AUTOSAR 中 Trusted Platform(可信平台)详解
  • 2510rs,rust清单2
  • PINN物理信息神经网络股票价格预测模型Matlab实现
  • 2510rs,rust清单3
  • 用ps做网站方法茂名建站模板搭建
  • 怎么建设vip电影网站wordpress轮播图设置
  • docker 更新layer
  • 基于卷积神经网络的香蕉成熟度识别系统,resnet50,vgg16,resnet34【pytorch框架,python代码】
  • 深度学习YOLO实战:6、通过视频案例,解析YOLO模型的能力边界与选型策略
  • C# 识别图片中是否有人
  • [Power BI] 漏斗图(Funnel Chart)