TCP三次握手四次挥手

1. 三次握手

三次握手:建立连接 四次挥手:释放连接

1.三次握手

  1. 开始前:客户端处于close状态,服务端属于listen状态
  2. 开始:
  • 第一次握手:客户端给服务端发送syn报文,并指定客户端的初始化序列号ISN(客户端处于SYN_SENT状态
  • 第二次握手:服务端接收到客户端报文,并生成SYN报文,指定服务端的初始化序列号,给客户端发送SYN报文、初始化序列号、ACK值(使用客户端的序列号+1)(服务端处于SYN_RCVD接收状态
  • 第三次握手:客户端接收到SYN报文后,会发送SYN报文、ACK值(服务器的序列号值+1),表示已收到服务端请求,此时ACK报文段可携带请求数据,不携带数据则不消耗序号。

1.1 为什么需要三次握手,两次不行吗?

(1)第一次握手:客户端发网络包,服务端收到(证明客户端发送能力、服务端接受能力没问题

(2)第二次握手:服务端发网络包,客户端收到(服务端发送能力,客户端接受能力没问题,但是此时服务端不知道客户端的接受能力是否正常

(3)第三次握手:客户端发网络包,服务端收到(客户端、服务端接收发送能力均正常

 1.2试想如果是用两次握手,则会出现下面这种情况

     客户端发出请求,但是请求报文丢失,客户端此时重新发送报文、服务端正常接受确认链接,正常交易。但是第一个丢失的报文段只是在某个网络节点滞留,等第二次请求连接释放后才到达服务端,此时服务端以为客户端发送两次请求,导致服务端再次发送请求给客户端,但是客户端忽略(浪费资源)

1.3 什么是半连接队列?

     服务端第一次接受客户端的SYN后,服务端处于SYN_RCVD状态,此时双方还没有完全建立其连接,此时的连接会被放到半连接队列,三次握手结束后,会把连接放入到全连接队列

 1.4 三次握手过程中可以携带数据吗?

      其实第三次握手的时候,是可以携带数据的。但是,第一次、第二次握手不可以携带数据

     为什么这样呢?大家可以想一个问题,假如第一次握手可以携带数据的话,如果有人要恶意攻击服务器,那他每次都在第一次握手中的 SYN 报文中放入大量的数据。因为攻击者根本就不理服务器的接收、发送能力是否正常,然后疯狂着重复发 SYN 报文的话,这会让服务器花费很多时间、内存空间来接收这些报文。

也就是说,第一次握手不可以放数据,其中一个简单的原因就是会让服务器更加容易受到攻击了。而对于第三次的话,此时客户端已经处于 ESTABLISHED 状态。对于客户端来说,他已经建立起连接了,并且也已经知道服务器的接收、发送能力是正常的了,所以能携带数据也没啥毛病。

 2. 四次挥手

(1)开始前:服务端、客户端均属于确认状态

(2)第一次挥手:客户端发起关闭请求,客户端发送FIN报文及序列号(客户端此时处于FIN_WAIT状态

(3)第二次挥手:服务端收到FIN报文,发出确认报文ACK值为序列号+1(服务端此时处于CLOSE_WAIT 状态

(4)第三次挥手:服务端发起关闭请求,服务端发送FIN报文及序列号(服务端处于最后确认状态

(5)第四次挥手:客户端收到FIN报文,客户端发送ACK报文、序列号+1回应,服务端收到后关闭连接(服务端此时处于关闭状态

TCP 连接的拆除需要发送四个包,因此称为四次挥手(Four-way handshake),客户端或服务端均可主动发起挥手动作。

 2.1 挥手为什么需要四次?

因为当服务端收到客户端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当服务端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉客户端,“你发的FIN报文我收到了”。只有等到我服务端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四次挥手。

你可能感兴趣的:(网络,tcp/ip,网络,java)