tcp的三次握手和四次挥手
1.tcp三次握手
客户端和服务端都需要知道各自可收发,因此需要三次握手。
三次握手可以简化为:
C(客户端)发起请求连接 S(服务端)确认,S也发起连接C确认。
每次握手的作用:
第一次握手:S只可以确认自己可以接受C发送的报文段。
第二次握手:C可以确认S收到了自己发送的报文段,并且可以确认自己可以接受S发送的报文段。
第三次握手:S可以确认C收到了自己发送的报文段。
tcp三次握手过程如下:
三次握手其实就是指建立一个TCP连接时,需要客户端和服务端总共发送3个包。
进行三次握手的主要作用就是为了确认双方的接收能力和发送能力是否正常、指定的自己的初始化序列号为后面的可靠的传送做准备。
实质上其实就是连接服务器指定端口,建立TCP连接,并同步连接双方的序列号和确认号,交换TCP窗口大小信息。
刚开始客户端处于closed的状态,服务端处于listen状态。
第一次握手:客户端给服务端发一个SYN报文,并指明客户端的初始化序列号ISN,此时客户端处于SYN-SEND状态。
首部的同步位SYN=1,初始序号seq=x,SYN=1的报文段不能携带数据,但要消耗掉一个序号。
第二次握手:服务器收到客户端的SYN报文之后,会以自己的SYN报文作为应答,并且也是指定了自己的初始化序列号ISN。同时会把客户端的ISN+1作为ACK的值,表示自己已经收到了客户端的SYN,此时服务器处于SYN_RCVD的状态。
在确认报文段中SYN=1,ACK=1,确认号ack=x+1,初始序号seq=y
第三次握手:客户端收到SYN报文之后,会发送一个ACK报文,当然,也是一样把服务器的ISN+1作为ACK的值,表示已经收到了服务器的SYN报文,此时客户端处于ESTABLISHED状态。服务器收到ACK报文之后,也处于ESTABLISHED状态,此时,双方已建立起了连接。
确认报文段ACK=1,确认号ack=y+1,序号seq=x+1(初始为seq=x,第二个报文段所以要+1),ACK报文段可以携带数据,不携带数据则不消耗序号。
TCP三次握手的建立连接过程就是相互确认初始序号的过程,告诉对方,什么样序号的报文段能够被正确接收。
第三次握手的作用?
是为了确认双方的接收能力和发送能力都正常。客户端对服务器端的初始序号的确认。如果只是用两次握手,那么服务器就没办法知道自己的序号是否已经被确认。同时这样也是为了防止失效的请求报文段被服务器接收,而出现错误的情况。
2.tcp四次挥手
刚开始双方都处于ESTABLISHED状态,假如是客户端先发起关闭请求。
tcp四次挥手过程如下:
第一次挥手:客户端会发送一个FIN报文,报文中会指定一个序列号。此时客户端处于FIN_WAIT1状态。
即发出连接释放报文段(FIN=1,序号 seq=u),并停止再发送数据, 主动关闭 TCP 连接,进入 FIN_WAIT1(终止等待 1)状态,等待服务 端的确认。
第二次挥手:服务端收到 FIN 之后,会发送 ACK 报文,且把客户端 的序列号值 +1 作为 ACK 报文的序列号值,表明已经收到客户端的 报文了,此时服务端处于 CLOSE_WAIT 状态。
即服务端收到连接释放报文段后即发出确认报文段(ACK=1,确认号 ack=u+1,序号 seq=v),服务端进入 CLOSE_WAIT(关闭等待)状态, 此时的 TCP 处于半关闭状态,客户端到服务端的连接释放。客户端收到服务端的确认后,进入 FIN_WAIT2(终止等待 2)状态,等待服务 端发出的连接释放报文段。
第三次挥手:如果服务端也想断开连接了,和客户端的第一次挥手一 样,发给 FIN 报文,且指定一个序列号。此时服务端处于 LAST_ACK 的状态。
即服务端没有要向客户端发出的数据,服务端发出连接释放报文段 (FIN=1,ACK=1,序号 seq=w,确认号 ack=u+1),服务端进入 LAST_ACK (最后确认)状态,等待客户端的确认。
第四次挥手:客户端收到 FIN 之后,一样发送一个 ACK 报文作为应 答,且把服务端的序列号值 +1 作为自己 ACK 报文的序列号值,此 时客户端处于 TIME_WAIT 状态。需要过一阵子以确保服务端收到自 己的 ACK 报文之后才会进入 CLOSED 状态,服务端收到 ACK 报文之 后,就处于关闭连接了,处于 CLOSED 状态。
即客户端收到服务端的连接释放报文段后,对此发出确认报文段 (ACK=1,seq=u+1,ack=w+1),客户端进入 TIME_WAIT(时间等待) 状态。此时 TCP 未释放掉,需要经过时间等待计时器设置的时间 2MSL 后,客户端才进入 CLOSED 状态。
为什么需要四次挥手呢?
因为当服务端收到客户端的 SYN 连接请求报文后,可以直接发送 SYN+ACK 报文。其中 ACK 报文是用来应答的,SYN 报文是用来同步的。 但是关闭连接时,当服务端收到 FIN 报文时,很可能并不会立即关闭 SOCKET,所以只能先回复一个 ACK 报文,告诉客户端,“你发的 FIN 报文我收到了”。只有等到我服务端所有的报文都发送完了,我才能 发送 FIN 报文,因此不能一起发送,故需要四次挥手。
TCP 使用四次挥手的原因?
是因为 TCP 的连接是全双工的,所以需要 双方分别释放到对方的连接,单独一方的连接释放,只代 表不能再 向对方发送数据,连接处于的是半释放的状态。
最后一次挥手中,客户端会等待一段时间再关闭的原因,是为了防止 发送给服务器的确认报文段丢失或者出错,从而导致服务器 端不能 正常关闭。
前端面试的一些常问问题、问题的具体实现(可直接运行)以及底层原理