一、TCP链接的几种状态
CLOSED
代表初始状态。
LISTEN
这也是一个非常简单的状态,表明服务器端SOCKET正在监听并且可以接受连接。
SYN_RCVD
该状态表明已收到SYN 消息。该状态通常是建立TCP 连接时服务器端SOCKET 三向握手会话期间的中间状态。通过netstat status 验证这一点很困难,除非您专门编写客户端测试程序并在3 次TCP 握手期间有意发送最终ACK 消息。因此,在该状态下,收到客户端的ACK消息后,就进入ESTABLISHED状态。
SYN_SENT
此条件与SYN_RCVD 相呼应。当客户端SOCKET进行CONNECT连接时,它首先发送一条SYN报文,因此它随后进入SYN_SENT状态,等待服务器发送三次握手中的第二条报文。 SYN_SENT状态表示客户端发送了SYN消息。
ESTABLISHED
这是不言自明的,意味着连接已经建立。
FIN_WAIT_1
这种情况必须仔细解释。其实FIN_WAIT_1和FIN_WAIT_2状态的真正含义是等待对方的FIN报文。这两种状态的区别在于: FIN_WAIT_1状态实际上意味着当SOCKET处于ESTABLISHED状态时它正在主动尝试关闭连接并向对方发送FIN报文。此时SOCKET进入FIN_WAIT_1状态。一旦对端响应ACK消息,它就进入FIN_WAIT_2状态。当然,在正常的现实情况下,FIN_WAIT_1状态通常是不可见的,因为无论如何对方都必须立即响应ACK消息。 FIN_WAIT_2 状态可以使用netstat 进行验证。
FIN_WAIT_2
该条件已在上面详细解释过。事实上,一个处于FIN_WAIT_2状态的SOCKET就代表了一个半连接。即一方请求关闭连接,但告诉另一方自己还有数据要发送。稍后关闭连接。
TIME_WAIT
表示你已经收到对方的FIN报文,并发送了ACK报文。 2MSL后返回CLOSED可用状态。如果对方在FIN_WAIT_1状态下收到同时带有FIN和ACK标志的报文,则可以直接进入TIME_WAIT状态,而无需经过FIN_WAIT_2状态。
CLOSING
这种情况非常特殊,在现实生活中很少发生。这是一种相对罕见的异常情况。一般情况下,如果要发送FIN报文,必须先收到(或同时收到)对方的ACK报文,然后再收到对方的FIN报文。但CLOSING状态是指发送FIN报文后,并没有收到对方的ACK报文,而是收到了对方的FIN报文。什么情况下会出现这种情况呢?其实仔细想想,这个结论也不难得出。也就是说,如果双方几乎同时关闭SOCKET,则双方会同时发送FIN报文,并显示CLOSING状态,表示双方正在关闭SOCKET连接。
CLOSE_WAIT
这个状态实际上意味着它正在等待关闭。我该如何理解呢?当对端关闭SOCKET并向自己发送FIN报文时,系统肯定会回复对端一个ACK报文,此时进入CLOSE_WAIT状态。接下来您真正需要考虑的是您是否还有数据要发送给对方。如果没有,则关闭SOCKET并向对方发送FIN报文。即关闭连接。因此,如果处于CLOSE_WAIT状态,则必须等待直到连接关闭。
LAST_ACK
该状态在一方发送FIN报文后被动关闭,最后等待另一方的ACK报文。一旦收到ACK消息,就可以进入CLOSED可用状态。
二、TCP链接建立时的三次握手
原文链接:
简单介绍下三次握手:
初始握手:客户端向服务器发送消息。
第二次握手:服务器收到消息后,向客户端回复消息。
第三次握手:客户端收到消息后,向服务器回复消息。
三次握手实际上意味着客户端和服务器在建立TCP 连接时总共必须发送三个数据包。三向握手的主要功能是验证双方是否有能力发送和接收,并为后续的可靠传输指定唯一的初始化序列号。本质上,它连接到服务器上的指定端口,建立TCP连接,同步双方的序列号和确认号,并交换TCP窗口大小信息。
下图展示了使用WireShark(网络数据包分析软件)捕获的TCP链路的3次握手过程。前三项分别对应一个3次握手过程。
最初,客户端处于关闭状态,服务器处于监听状态。
执行3 次握手。
初始握手:客户端向服务器发送SYN报文,表明客户端的初始化序列号ISN。此时,客户端处于SYN_SENT状态。报头中的同步位SYN=1,初始序列号seq=x,SYN=1的报文段不能携带数据,但序列号被消耗。
第二次握手:服务器收到客户端的SYN报文后,用自己的SYN报文进行响应,同时也指定自己的初始化序列号ISN。同时用客户端的ISN+1作为ACK值,表明此时服务器处于SYN_RCVD状态。
第三次握手:客户端收到SYN报文后,发送ACK报文。当然,服务器的ISN+1表明此时已经从服务器收到了SYN报文。客户端已建立状态。服务器收到ACK消息后,也进入ESTABLISHED状态。至此,双方已经建立了连接。
为什么需要三次握手,两次不行吗?
为了弄清楚这个问题,我们首先要明白三次握手的目的是什么,两次握手是否就能达到同样的目的。
初次握手:客户端发送网络数据包,服务器接收。这样,服务器就可以断定客户端的发送能力和服务器的接收能力都是正常的。
第二次握手:服务器发送数据包,客户端接收。这样,客户端就可以断定服务器的发送/接收能力和客户端的发送/接收能力都没有问题。但此时服务器无法验证客户端的接收能力是否正常。
第三次握手:客户端发送数据包,服务器接收。这样,服务器就可以断定客户端的发送和接收能力是好的,并且服务器本身的发送和接收能力也是好的。
什么是半连接队列?
服务器第一次收到客户端的SYN后,处于SYN_RCVD状态。此时,服务器将请求的连接在此状态下排队。这个队列是一个半组合队列。
当然,还有一个完整的连接队列。这意味着3次握手完成,建立的连接被放入全连接队列中。如果队列已满,可能会发生数据包丢失。
关于SYN-ACK 重传次数的一点补充。
如果服务器发送SYN-ACK报文后没有收到客户确认报文,则等待一定时间后仍未收到客户确认报文,服务器将首次重发该报文。这是第二次了。如果重传次数超过系统规定的最大重传次数,系统将从半连接队列中删除该连接信息。
请注意,每次重传的延迟不一定相同,通常间隔时间呈指数增长,例如1秒、2秒、4秒、8秒等。
ISN(Initial Sequence Number)是固定的吗?
当对等方发送SYN 来建立连接时,它会选择该连接的第一个序列号。 ISN 随着时间的推移而变化,因此每个连接都分配有不同的ISN。 ISN 可以看作是一个32 位计数器,每4ms 加1。以这种方式选择序列号的目的是为了防止网络中延迟的数据包稍后发送并导致连接的一方误解序列号。
三向握手的关键特征之一是客户端和服务器交换ISN(初始序列号),以便对方知道下次收到数据时如何根据序列号组装数据。如果ISN是固定的,攻击者就更容易猜测后续的确认号,因此ISN是动态生成的。
原创文章,作者:CSDN,如若转载,请注明出处:https://www.sudun.com/ask/93855.html