介绍一下TCP三次握手的过程
介绍TCP三次握手应该从3个方面进行回答,分别是数据包名称,客户端与服务端的状态变化,数据包的序号变化。而不能只是简单回答发送的数据包名称。
TCP三次握手的过程如下:
TCP3次握手改为2次可以吗?
不可以,理由如下:
ACK数据包消耗TCP的序号吗?
ACK数据包分为2类:纯ACK数据包和携带数据的ACK数据包,对于纯ACK数据包,不消耗序号,例如第三次握手。因为纯ACK数据包仅仅表示应答,不携带任何有效数据;对于携带数据的ACK数据包,例如PSH+ACK的数据包,由于这种数据包属于捎带应答,TCP为给每一个字节的有效载荷进行编号,这种数据包消耗TCP序号
TCP3次握手可以携带有效数据吗?
第一次和第二次握手不能携带有效数据,第三次可以,原因如下:
第一次和第二次握手客户端与服务端都不是ESTABLISHED状态
如果第一次和第二次可以携带数据的话,那么服务器很容易受到攻击,客户端可以在第一次发送的SYN中携带大量数据消耗服务端的资源;如果第二次握手可以携带数据,也会消耗服务端的资源。
第三次可以携带数据的原因是客户端处于ESTABLISHED状态,认为连接已经建立完毕,因此理论上可以携带数据,不过实际上由于TCP的慢启动机制,很少这样做
TCP3次握手从功能上讲是用来建立连接而非发送数据,因此第3次握手虽然从理论上讲可以携带数据,但是一般不携带
服务端不进行accept,最多有多少个连接可以建立成功?
服务端不进行accept,最多可以建立成功的连接个数取决于listen函数的第2个参数,listen函数的第2个参数+1
是全连接队列的最大长度。
全连接队列的最大长度有什么用?为什么要有全连接队列?全连接队列的长度为什么不能太长?
全连接队列的最大长度是服务端不进行accpet或者来不及accpet时TCP底层能够能够保留的最大连接个数。全连接队列存在的意义是当服务端负载较重时,能够尽可能多的保存来不及处理的连接,当服务端处理完毕别的连接之后可以立即处理全连接队列中的连接。全连接队列的长度不能太长,否则排在全连接队列尾部的客户端等待服务的时间会很长,影响使用体验。
TCP3次握手中,连接的序号一定要从0开始吗?
不一定,无论是客户端第一次SYN,还是服务端的SYN+ACK,其序号都是随机生成的,主要是为了提高连接的安全性,如果连接的序号都是从0开始,那么攻击者很容易推算出双方数据通信的序号,从而破坏连接。使用随机生成的序号可以防止被恶意攻击。
TCP通过3次握手最多可以建立多少个连接?
TCP最多可以建立连接的数量取决于操作系统,在Linux系统中,socket的底层是通过文件的方式实现的,每建立一个连接,都会消耗一个文件描述符,因此TCP底层最多可以建立连接的个数取决于一个进程最多能够打开的文件描述符个数,在Linux中可以使用ulimit -a
查看
介绍一下TCP四次挥手的过程?
从3个方面介绍TCP四次挥手的过程:
TCP3次握手的过程中,为什么要协商MSS?
TCP3次握手协商MSS的主要原因是避免数据包在IP层分片。
四次挥手阶段能否发送应用层数据?
四次挥手阶段可以发送应用层数据。主动断开连接方发送FIN,被动断开连接方回复ACK表示主动断开连接方不会发送数据,但是依然可以接收数据,被动断开连接方可以给主动断开连接方发送数据。
四次挥手的报文能否携带应用层数据?
理论上而言可行,主动断开连接方发送FIN表示后续主动断开连接方不会发送数据,但是这个FIN报文可以携带应用层数据,不过一般不这样做,因为四次挥手的功能是用来断开连接的,而不是用来传输数据的。
服务端出现大量的CLOSE_WAIT状态的链接,是什么原因?有什么危害?
四次挥手的过程中,被动断开连接的一方在收到第一个FIN之后会处于CLOSE_WAIT状态,被动断开连接方调用close函数后TCP底层才会给主动断开连接一方发送FIN报文,服务端出现大量CLOSE_WAIT状态的连接,说明服务端是被动断开连接方,且服务端没有调用close函数,在这种情况下造成的直接后果就是文件描述符泄漏,占用被动断开连接方的资源。
补充:被动断开连接方忘记调用close关闭文件描述符,这种情况下被动断开连接方会一直处于CLOSE_WAIT状态,主动断开连接方会一直处于FIN_WAIT2状态,称之为半开连接
,针对半开连接,操作系统会在特定的超时时间后强制关掉这个链接
TCP四次挥手,主动断开连接方为什么要等待2MSL(maximum survival time)的时间?
相似问题:
MSL指的报文的最大生存时间(maximum survival time),主动断开连接的一方需要等待2MSL,主要原因是担心最后一个ACK丢失,这个2MSL=最后一个ACK报文的MSL+被动断开连接方重传的FIN报文的MSL
TCP报文的序号是最大是多少,超过这个值应该怎么办?
在TCP报头中序号是32位无符号整数,最大是232-1,超过232-1,会出发序号回绕
的机制,类似无符号char赋值257,实际为1
什么是TCP的确认应答机制?
TCP的确认应答机制是TCP保证可靠性的基础,指的是接收方需要对发送方的数据进行ACK应答,让发送发知道自己发送的数据已经被收到。确认应答是对数据和序号的确认,体现在TCP报头中就是32位确认序号,其含义是在确认序号之前的数据
接收方都
收到了
介绍一下TCP的滑动窗口机制
从以下几点介绍TCP的滑动窗口机制:
什么是TCP的超时重传机制?
TCP的超时重传机制指的是发送方在一定时间内没有收到接收方ACK的情况下会对数据进行补发,引发超时重传主要有下面这2种情况:
超时重传的时间是如何确认的?是固定的吗?
TCP的超时重传时间不是确定的,而是动态变化的,超时重传时间RTO(retransmission timeout)与报文往返时间RTT(round trip time)密切相关,一般而言,网络状况越好,RTT越小,RTO越小,网络状况越差,RTT越大,RTO也越大。
TCP如何提高传输效率?
TCP在保证可靠性的前提下有多种手段可以提高效率
TCP如何保证可靠性?
相似问题:TCP有哪些保证可靠性的策略?
TCP拥有众多策略保证可靠性
说一下TCP的快重传,快重传与超时重传的区别?
快重传指的是发送方收到3个相同的ACK确认报文时,对数据进行补发的一种机制,快重传与超时重传的区别如下:
虽然快重传的效率一般高于超时重传,但是快重传也存在效率问题,最典型的场景是在发送批量报文的时候中间报文大量丢失,此时发送方会收到大量重复的ACK,影响效率,为了解决快重传的效率问题,接收方在回复ACK时会在TCP报头的选项字段中向发送方说明哪些报文已经收到了,你需要补发哪些报文,具体操作是在40字节的选项字段中设置SACK字段,SACK字段包含Left Edge和Right Edge属性,left edge表示已经收到的不连续报文的第一个序号,right edge表示已经收到的不连续报文的最后一个序号+1,通过SACK属性中的left edge和right edge,发送方就可以知道哪些报文丢失了,从而针对性的进行补发
SYN报文什么情况下会被丢弃?
当全连接队列和半连接队列满了的时候SYN报文会被丢弃,当一个连接处于第二次握手而没有完成三次握手时,会被放入TCP的半连接队列,半连接队列的大小由配置文件tcp_max_syn_backlog
决定。
只有完成了3次握手连接才会从半连接队列转移到全连接队列,全连接队列的大小由配置文件somaxconn
和listen函数的第二个参数决定,因此当SYN报文被丢失,可以修改tcp_max_syn_backlog和somaxconn配置文件。
除此之外,还可以通过使用syncookies功能,在不使用半连接队列的情况下直接成功建立连接。
syncookies功能的作用:开启了syncookies功能的话,服务端收到第一个SYN之后,在回复的SYN+ACK报文中会携带一个cookie值,客户端的ACK需要携带这个cookie值进行校验,校验通过,直接将该连接放入全连接队列,而不需要使用半连接队列。syncookies功能是否开启由配置文件tcp_syncookies
决定。
0:表示关闭syncookies功能
1:表示只有当半连接队列满了才开启这个功能
2:无条件开启这个功能,这样的话半连接队列基本就没什么意义了
拔掉网线之后,TCP链接还存在吗?
拔掉网线之后,双方主机认为TCP连接在存在,如果拔掉网线之后还有数据传输,那么会一直触发超时重传,直到达到超时重传的最大次数tcp_retries2
,将会强制断开连接。
如果拔掉网线之后没有数据传输,那么会触发TCP的心跳机制,客户端/服务端主机会定期发送心跳报文以检测对方是否还在线,如果心跳报文没有响应,那么会强制断开连接。