基于Tcp协议的通信,客户端和服务器需要三次握手建立连接,四次挥手结束连接。目的是为了确认服务端和客户端的收发数据能力正常,通过ISN序列号来保证数据的可靠传输。
三次握手
1、客户端向服务器发起连接请求,发送一个SYN报文,并指明客户端初始化序列号ISN;客户端状态为SYN-sent。 2、服务期收到客户端连接请求,状态变为SYN-recv;服务器给客户端回应一个SYN报文,以及ACK数据(客户端的ISN+1),并指定自己的初始化序列号ISN。 3、客户端收到服务器发来的报文,状态为established;再给服务端发送一个 SYN报文,同样将服务端发来的ISN+1作为ACK的值。服务端收到报文后转台变为established。
为什么是三次握手,两次不行
三次握手是为了确认服务端和客户端收发数据能力正常。 第一次握手,客户端向服务端发送报文,服务端收到客户端发送的报文,服务端就可以确认客户端能够正常发送数据,服务端能够正常接收数据。 第二次握手,服务端给客户端响应报文,客户端收到数据,客户端就可以确认服务端和客户端的收发能力都正常,但此时服务端不能确定客户端的接受能力是否正常。 第三次握手,客户端收到数据后,给服务端再次发送报文,此时服务端收到数据后,就可以确定,客户端的接收数据能力也正常。
如果只有两次握手,那服务端只能确定客户端能够正常发送数据,不能确定客户端是否能够正常接收数据。此时会出现什么情况呢? 客户端发送请求连接,服务端收到并回应,此时建立好连接,然后客户端发送数据,客户端发送了两个报文段,第一个报文段再传输过程中延迟了,服务端先收到的第二个报文段,此时服务端会认为客户端没有收到响应报文,这个报文段是客户端建立新连接的请求,就响应给客户端一个响应报文,而客户端忽略服务端的响应报文,就会造成服务端一直在等待,浪费资源。
三次握手的作用
1、确认客户端和服务端双方收发数据的能力是否正常 2、指定自己的初始化序列号,为之后数据的可靠性传输做准备
ISN是固定的吗
ISN序列号主要是用来在三次握手过程中双方做交换,以便让对方知道接下来接受的数据的组装顺序,如果ISN是固定的,很容易让攻击者猜出后续的确认号,所以ISN是动态生成的。
三次握手过程中可以携带数据吗
第一次和第二次不可以,第三次握手可以携带数据。
举个例子,如果第一次握手可以携带数据,如果有人要恶意攻击服务器,那他每次都在第一次握手的SYN报文中放大量数据,恶意攻击者根本不关心服务器端的收发数据能力是否正常,所以他可以不停地重复发送SYN请求报文,这就造成服务器花费大量时间和内存来接收这些数据。所以第一次握手可以携带数据会让服务器更容易受到攻击。
第三次握手时,客户端已经收到服务端的响应报文,所以客户端可以确认客户端和服务端的收发能力都正常,而且客户端已经是established状态,即对于客户端来说已经建立起连接了,所以第三次握手携带数据是可以的。
半连接队列
服务器收到客户端的连接请求报文并发送响应报文给客户端,此时状态为SYN-recv,在收到客户端的确认报文之前,此时连接还未完全建立,叫做半连接,把这些连接放到一个队列里,这个队列叫做半连接队列,全连接队列就是放那些收到客户端确认报文,已经建立起的连接。如果队列满了,就可能出现丢包现象。
SYN-ACK重传机制:服务端没有收到客户端确认报文,会进行首次重传,隔段时间还是没有收到确认报文,会进行第二次重传,重传次数超过系统规定最大重传次数,就将此连接从半连接队列中删除。
四次挥手
1、客户端向服务端发送断开连接请求报文,即FIN包,同时指定一个seq序号。客户端状态为FIN-wait1,主动关闭tcp连接,并停止发送数据。 2、服务端收到客户端发送到报文,响应一个ACK报文,以客户端seq+1为ack值,并指定自己的seq序号;状态变为close_wait,等待,此时TCP处于半关闭状态,客户端收到响应的ACK报文后状态变为FIN-wait2,等待服务端发出连接释放报文。 3、如果服务端也想断开连接了,向客户端发送FIN报文,并指定一个seq序号,等待客户端确认,状态变为Last-ack。 4、客户端收到来自服务端的FIN报文,一样发送ACK报文给服务端,以服务端的seq+1为ack报文序列号值,客户端进入TIME-wait状态。等待计时器设置时间2MSL之后,释放连接,进入CLOSED状态,服务端收到确认报文后进入CLOSED状态。
为什么握手三次,而挥手需要四次
客户端请求连接时,向服务端发送SYN包,而服务端响应时,直接发送SYN+ACK包,SYN负责同步,ACK负责应答;而断开连接时,服务端收到客户端断开连接的请求时,需要等待报文发送完才能释放连接,所以只能先发送一个ACK包表示,我收到了你的请求,等服务端报文发送完,我再发送FIN包。所以需要四次挥手。
四次挥手释放连接时,等待2MSL的意义
MSL(Maximum Segment Lifetime)最长报文段寿命 等待2MSL是为了确保最后一个ACK响应报文能够到达服务器端,双方都能正常关闭连接。 客户端发送的ACK报文可能会丢失,如果客户端发送完ACK报文就直接进入CLOSED状态,而服务器端最后并没有收到确认报文,重传的FIN报文客户端也无法接收,就会导致服务器端无法正常关闭。同时避免下一个新的连接中出现旧的已失效的连接请求报文段。 Time-wait状态等待2MSL才能进入CLOSED状态,TIME-WAIT状态就是用来重发可能丢失的ACK报文。
|